package com.hdkj.lt.bf.service.impl;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Sets;
import com.hdkj.hussar.ApiResponse;
import com.hdkj.lt.base.constants.DictConstants;
import com.hdkj.lt.bf.entity.dto.*;
import com.hdkj.lt.bf.entity.vo.*;
import com.hdkj.lt.bf.mapper.*;
import com.hdkj.lt.bf.service.FhzgOperationAbnormalityService;
import com.hdkj.lt.bf.service.aspect.UserCountyCodeAuto;
import com.hdkj.lt.bf.service.voltageLimitViolation.FhzgVoltageLimitViolationPowerCutService;
import com.hdkj.lt.core.bizms.modle.dto.FhzgGridOperationAbnormalityDTO;
import com.hdkj.lt.core.bizms.modle.po.operationAbnormality.*;
import com.hdkj.lt.core.bizms.modle.po.voltageLimitViolation.FhzgVoltageLimitViolationPowerCut;
import com.hdkj.lt.core.sys.dao.FhzgOrganSuffixMapper;
import com.hdkj.lt.modle.dto.abnormal.ApiAbnormalDataDTO;
import com.hdkj.lt.modle.dto.abnormal.SwitchDetailDTO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class FhzgOperationAbnormalityServiceImpl extends ServiceImpl<FhzgGridOperationAbnormalityMapper, FhzgGridOperationAbnormality> implements FhzgOperationAbnormalityService {

    private final FhzgGridOperationAbnormalityMapper fhzgGridOperationAbnormalityMapper;

    private final FhzgAwaitTransferPathDetailMapper fhzgAwaitTransferPathDetailMapper;

    private final FhzgSwitchingSequenceMapper fhzgSwitchingSequenceMapper;

    private final FhzgLineLoadfactorLossMapper fhzgLineLoadfactorLossMapper;

    private final FhzgVoltageViolationMapper fhzgVoltageViolationMapper;

    private final FhzgOrganSuffixMapper fhzgOrganSuffixMapper;

    private final FhzgOperationAbnormalityTransferAreaResultMapper transferAreaResultMapper;

    private final FhzgVoltageLimitViolationPowerCutService violationPowerCutService;

    @Override
    @UserCountyCodeAuto(sourceFiled = "countyCode", targetFiled = "countyCodeList")
    public Page<FhzgGridOperationAbnormalityVO> getOperationAbnormalityList(FhzgGridOperationAbnormalityDTO queryDTO) {
        Page<FhzgGridOperationAbnormalityVO> page = new Page<>();
        page.setCurrent(queryDTO.getPageNum());
        page.setSize(queryDTO.getPageSize());
        List<FhzgGridOperationAbnormalityVO> operationAbnormalityList = fhzgGridOperationAbnormalityMapper.getOperationAbnormalityList(queryDTO);
        operationAbnormalityList.forEach(i -> {
            i.setPlanCreateTime(fhzgGridOperationAbnormalityMapper.getPlanCreateTimeById(i.getId()));
        });
        page.setRecords(operationAbnormalityList);
        page.setTotal(operationAbnormalityList.size());
        return page;
    }

    //运行调优列表查询新

    @Override
    @UserCountyCodeAuto(sourceFiled = "countyCode", targetFiled = "countyCodeList")
    public Page<FhzgAbnormalityWithVolVO> getOperationAbnormalityListNew(FhzgGridOperationAbnormalityDTO queryDTO) {
        Page<FhzgAbnormalityWithVolVO> result = new Page<>();
        List<FhzgAbnormalityWithVolVO> records = new ArrayList<>();
        //运行调优数据列表
        Page<FhzgGridOperationAbnormalityVO> page = new Page<>();
        page.setCurrent(queryDTO.getPageNum());
        page.setSize(queryDTO.getPageSize());
        Page<FhzgGridOperationAbnormalityVO> abnormalityList = getOperationAbnormalityList(queryDTO);
        if (abnormalityList.getTotal() > 0) {
            abnormalityList.getRecords().forEach(i -> {
                FhzgAbnormalityWithVolVO abnormality = new FhzgAbnormalityWithVolVO();
                abnormality.setType(0);
                abnormality.setTime(i.getPlanCreateTime());
                abnormality.setAbnormalityDTO(i);
                records.add(abnormality);
            });
        }
        //电压越限数据
        VolPowerCutDTO volPowerCutDTO = VolPowerCutDTO.builder()
                .volType(queryDTO.getVoltageTypeBefore())
                .countyCode(queryDTO.getCountyCode())
                .feederName(queryDTO.getFeederName())
                .countyCodeList(queryDTO.getCountyCodeList())
                .volStartTime(queryDTO.getVolStartTime())
                .volEndTime(queryDTO.getVolEndTime())
                .pageNum(queryDTO.getPageNum())
                .pageSize(queryDTO.getPageSize())
                .build();
        Page<FhzgVoltageLimitViolationPowerCut> volPageList =
                violationPowerCutService.getVolPowerCutList(volPowerCutDTO);
        if (volPageList.getTotal() > 0) {
            volPageList.getRecords().forEach(i -> {
                FhzgAbnormalityWithVolVO abnormality = new FhzgAbnormalityWithVolVO();
                abnormality.setType(1);
                abnormality.setTime(i.getEventCreateTime());
                abnormality.setViolationPowerCut(i);
                records.add(abnormality);
            });
        }

        //按时间排序并分页处理
        records.sort(Comparator.comparing(FhzgAbnormalityWithVolVO::getTime).reversed());
        int total = records.size();
        int start = Math.min((queryDTO.getPageNum() - 1) * queryDTO.getPageSize(), total);
        int end = Math.min(queryDTO.getPageNum()  * queryDTO.getPageSize(), total);
        result.setSize(queryDTO.getPageSize());
        result.setCurrent(queryDTO.getPageNum());
        result.setRecords(records.subList(start, end));
        result.setTotal(total);
        return result;
    }

    @Override
    public List<FhzgAwaitTransferPathDetailVO> getAwaitTransferPathDetail(String oaId) {
        LambdaQueryWrapper<FhzgOperationAbnormalityAwaitTransferPathDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FhzgOperationAbnormalityAwaitTransferPathDetail::getOaId, oaId);
        Map<String, List<FhzgOperationAbnormalityAwaitTransferPathDetail>> groupedMap = fhzgAwaitTransferPathDetailMapper.selectList(wrapper)
                .stream().collect(Collectors.groupingBy(FhzgOperationAbnormalityAwaitTransferPathDetail::getGroupLineId));
        List<FhzgAwaitTransferPathDetailVO> result = new ArrayList<>();
        int groupLineNo = 1;
        for (Map.Entry<String, List<FhzgOperationAbnormalityAwaitTransferPathDetail>> entry : groupedMap.entrySet()) {
            FhzgAwaitTransferPathDetailVO vo = new FhzgAwaitTransferPathDetailVO();
            vo.setGroupLineId(entry.getKey());
            vo.setGroupLineNo(groupLineNo++);
            List<FhzgOperationAbnormalityAwaitTransferPathDetail> sortedList = entry.getValue().stream()
                    .sorted(Comparator.comparing(detail -> !"1".equals(detail.getTransferType())))
                    .collect(Collectors.toList());
            FhzgOperationAbnormalityAwaitTransferPathDetail feedOut = sortedList.get(0);
            FhzgOperationAbnormalityAwaitTransferPathDetail feedIn = sortedList.get(1);
            BigDecimal currentChange = null;
            if (feedOut.getBeforeCurrent() != null && feedOut.getAfterCurrent() != null) {
                currentChange = feedOut.getAfterCurrent().subtract(feedOut.getBeforeCurrent());
            }
            vo.setLineNameIn(feedIn.getLineName())
                    .setAfterLoadFactorIn(feedIn.getAfterLoadFactor())
                    .setLoadChangeIn(feedIn.getLoadChange())
                    .setLineIdIn(feedIn.getLineId())
                    .setLineNameOut(feedOut.getLineName())
                    .setLineIdOut(feedOut.getLineId())
                    .setAfterLoadFactorOut(feedOut.getAfterLoadFactor())
                    .setLoadChangeOut(feedOut.getLoadChange())
                    .setAfterCurrent(currentChange)
                    .setSwitchName(feedIn.getCloseSwitchName())
                    .setSwitchId(feedIn.getCloseSwitchId());

//            vo.setAwaitTransferPathDetails(sortedList);
            result.add(vo);
        }
        return result;
    }

    @Override
    public Page<FhzgOperationAbnormalitySwitchingSequence> getSwitchingSequence(FhzgGridOperationAbnormalityDTO queryDTO) {
        Page<FhzgOperationAbnormalitySwitchingSequence> page = new Page<>();
        page.setCurrent(queryDTO.getPageNum());
        page.setSize(queryDTO.getPageSize());
        LambdaQueryWrapper<FhzgOperationAbnormalitySwitchingSequence> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FhzgOperationAbnormalitySwitchingSequence::getOaId, queryDTO.getOaId())
                .orderByAsc(FhzgOperationAbnormalitySwitchingSequence::getSwitchingSeq);
        Page<FhzgOperationAbnormalitySwitchingSequence> listPage = fhzgSwitchingSequenceMapper.selectPage(page, wrapper);
        listPage.getRecords().forEach(e -> {
            int index = e.getSwitchingSeq() + 1;
            e.setSwitchingSeq(index);
        });
        return listPage;
    }

    /**
     * 获取线路损耗数据
     *
     * @param queryDTO
     * @return
     */
    @Override
    public Page<FhzgOperationAbnormalityLineLoadfactorLoss> getLineLoadfactorLoss(FhzgGridOperationAbnormalityDTO queryDTO) {
        Page<FhzgOperationAbnormalityLineLoadfactorLoss> page = new Page<>();
        page.setCurrent(queryDTO.getPageNum());
        page.setSize(queryDTO.getPageSize());
        LambdaQueryWrapper<FhzgOperationAbnormalityLineLoadfactorLoss> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(FhzgOperationAbnormalityLineLoadfactorLoss::getOaId, queryDTO.getOaId());
        //判断条件
        if (queryDTO.getLoadTypeBefore() != null && !queryDTO.getLoadTypeBefore().isEmpty()) {
            if (queryDTO.getLoadTypeBefore().contains(0)) {
                //转供前负载率大于80%即为重载
                wrapper.or(q -> q.gt(FhzgOperationAbnormalityLineLoadfactorLoss::getBeforeFactor, new BigDecimal("80")));
            }
            if (queryDTO.getLoadTypeBefore().contains(1)) {
                //转供前负载率大于100%即为过载
                wrapper.or(q -> q.gt(FhzgOperationAbnormalityLineLoadfactorLoss::getBeforeFactor, new BigDecimal("100")));
            }
            if (queryDTO.getLoadTypeBefore().contains(0) && !queryDTO.getLoadTypeBefore().contains(1)) {
                //仅重载时剔除过载数据
                wrapper.and(q -> q.le(FhzgOperationAbnormalityLineLoadfactorLoss::getBeforeFactor, new BigDecimal("100")));
            }
        }
        if (queryDTO.getLoadTypeAfter() != null && !queryDTO.getLoadTypeAfter().isEmpty()) {
            if (queryDTO.getLoadTypeAfter().contains(0)) {
                //转供后负载率大于80%即为重载
                wrapper.or(q -> q.gt(FhzgOperationAbnormalityLineLoadfactorLoss::getAfterFactor, new BigDecimal("80")));
            }
            if (queryDTO.getLoadTypeAfter().contains(1)) {
                //转供后负载率大于100%即为过载
                wrapper.or(q -> q.gt(FhzgOperationAbnormalityLineLoadfactorLoss::getAfterFactor, new BigDecimal("100")));
            }
            if (queryDTO.getLoadTypeAfter().contains(0) && !queryDTO.getLoadTypeAfter().contains(1)) {
                //仅重载时剔除过载数据
                wrapper.and(q -> q.le(FhzgOperationAbnormalityLineLoadfactorLoss::getAfterFactor, new BigDecimal("100")));
            }
            if (queryDTO.getLoadTypeAfter().contains(2)) {
                //转供后负载率变化大于0即为负载率上升
                wrapper.or(q -> q.gt(FhzgOperationAbnormalityLineLoadfactorLoss::getChangeFactor, new BigDecimal("0")));
            }
            if (queryDTO.getLoadTypeAfter().contains(3)) {
                //转供后负载率变化大于0即为负载率下降
                wrapper.or(q -> q.lt(FhzgOperationAbnormalityLineLoadfactorLoss::getChangeFactor, new BigDecimal("0")));
            }
        }
        List<FhzgOperationAbnormalityLineLoadfactorLoss> list = fhzgLineLoadfactorLossMapper.selectList(wrapper);
        List<FhzgOperationAbnormalityLineLoadfactorLoss> listMiddle = list.stream().filter(l -> l.getOaId().equals(Long.valueOf(queryDTO.getOaId()))).collect(Collectors.toList());
        Pageable pageable = PageRequest.of(queryDTO.getPageNum(), queryDTO.getPageSize());
        int start = (queryDTO.getPageNum() - 1) * queryDTO.getPageSize();
        List<FhzgOperationAbnormalityLineLoadfactorLoss> listResult = listMiddle.subList(start, Math.min(start + pageable.getPageSize(), listMiddle.size()));
        page.setTotal(listMiddle.size());
        listResult.forEach(i -> {
            i.setLineLossBefore(i.getLineLossBefore().multiply(new BigDecimal("1000")));
            i.setLineLossAfter(i.getLineLossAfter().multiply(new BigDecimal("1000")));
            i.setLineLossChange(i.getLineLossChange().multiply(new BigDecimal("1000")));
        });
        page.setRecords(listResult);
        return page;
    }

    /**
     * 获取电压越限数据
     *
     * @param queryDTO
     * @return
     */
    @Override
    public Page<FhzgOperationAbnormalityVoltageViolation> getVoltageViolation(FhzgGridOperationAbnormalityDTO queryDTO) {
        Page<FhzgOperationAbnormalityVoltageViolation> page = new Page<>();
        page.setCurrent(queryDTO.getPageNum());
        page.setSize(queryDTO.getPageSize());
        LambdaQueryWrapper<FhzgOperationAbnormalityVoltageViolation> wrapper = new LambdaQueryWrapper<>();
        //判断条件
        if (queryDTO.getVoltageTypeBefore() != null && !queryDTO.getVoltageTypeBefore().isEmpty()) {
            queryDTO.getVoltageTypeBefore().forEach(code -> {
                switch (code) {
                    case 0:
                        //转供前电压大于10.7kV即为越上限
                        wrapper.or(q -> q.gt(FhzgOperationAbnormalityVoltageViolation::getBeforeVoltage, new BigDecimal("10.7")));
                        break;
                    case 1:
                        //转供前电压小于9.3kV即为越下限
                        wrapper.or(q -> q.lt(FhzgOperationAbnormalityVoltageViolation::getBeforeVoltage, new BigDecimal("9.3")));
                        break;
                    default:
                        break;
                }
            });
        }
        if (queryDTO.getVoltageTypeAfter() != null && !queryDTO.getVoltageTypeAfter().isEmpty()) {
            queryDTO.getVoltageTypeAfter().forEach(vo -> {
                switch (vo) {
                    case 0:
                        //转供后电压大于10.7kV即为越上限
                        wrapper.or(q -> q.gt(FhzgOperationAbnormalityVoltageViolation::getAfterVoltage, new BigDecimal("10.7")));
                        break;
                    case 1:
                        //转供后电压小于9.3kV即为越下限
                        wrapper.or(q -> q.lt(FhzgOperationAbnormalityVoltageViolation::getAfterVoltage, new BigDecimal("9.3")));
                        break;
                    default:
                        break;
                }
            });
        }
        // wrapper.and(q -> q.eq(FhzgOperationAbnormalityVoltageViolation::getOaId, queryDTO.getOaId()));
        //wrapper.eq(FhzgOperationAbnormalityVoltageViolation::getOaId, queryDTO.getOaId());
        List<FhzgOperationAbnormalityVoltageViolation> list = fhzgVoltageViolationMapper.selectList(wrapper);
        List<FhzgOperationAbnormalityVoltageViolation> listMiddle = list.stream().filter(l -> l.getOaId().equals(Long.valueOf(queryDTO.getOaId()))).collect(Collectors.toList());
        Pageable pageable = PageRequest.of(queryDTO.getPageNum(), queryDTO.getPageSize());
        int start = (queryDTO.getPageNum() - 1) * queryDTO.getPageSize();
        List<FhzgOperationAbnormalityVoltageViolation> listResult = listMiddle.subList(start, Math.min(start + pageable.getPageSize(), listMiddle.size()));
        //新增判断电压越限标识
        listResult.forEach(e ->
        {
            if (e.getAfterVoltage().compareTo(BigDecimal.valueOf(10.7)) > 0) {
                e.setOverVoltageType(2);
            } else if (e.getAfterVoltage().compareTo(BigDecimal.valueOf(9.3)) < 0) {
                e.setOverVoltageType(1);
            } else {
                e.setOverVoltageType(3);
            }
        });
        page.setTotal(listMiddle.size());
        page.setRecords(listResult);
        return page;
    }

    @Override
    public List<BreakerAreaVO> getPathOverviewSwitch(OperationAbnormalityQueryDTO request) {
        List<String> kgPsrTypes = Arrays.asList(DictConstants.KG_PSR_TYPE.split(","));
        // 动态表名切换
        //*ztj ArgTableNameHandler.setArgument(fhzgOrganSuffixMapper.getOrganSuffixByPsrIdOrFeeder(null, request.getFeederId()));
        // 获取开关段信息
        List<FeederDeviceVO> feederDeviceList = fhzgGridOperationAbnormalityMapper.getBreakerAreaInfo(request.getOaId(), kgPsrTypes);
        // 被带供线路对应的中间开关信息
        Map<String, Map<String, List<String>>> afterFeederMap = feederDeviceList.stream().collect(Collectors.groupingBy(FeederDeviceVO::getAfterFeeder,
                Collectors.collectingAndThen(Collectors.toList(), subList -> subList.stream().sorted(Comparator.comparing(FeederDeviceVO::getSwitchingSeq))
                        .collect(Collectors.groupingBy(FeederDeviceVO::getFeeder, LinkedHashMap::new, Collectors.mapping(FeederDeviceVO::getPsrId, Collectors.toList()))))));
        // 按照开始开关分组排序
        Map<String, List<FeederDeviceVO>> collectMap = feederDeviceList.stream()
                .collect(Collectors.groupingBy(FeederDeviceVO::getSwitchId))
                .entrySet().stream()
                .sorted(Comparator.comparing(e -> e.getValue().get(0).getSwitchingSeq()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (perv, curr) -> perv, LinkedHashMap::new));
        // 返回值处理（注意根据开始开关分组有序的数据先查对侧后查本侧，取线路时只取对侧，需要保证第一条是对侧线）

        List<BreakerAreaVO> breakerAreaList = collectMap.entrySet().stream()
                .map(e -> {
                    BreakerAreaVO breakerArea = new BreakerAreaVO();
                    List<FeederDeviceVO> feederDevices = e.getValue();
                    List<String> midSwitchList = feederDevices.stream().map(FeederDeviceVO::getPsrId).collect(Collectors.toList());
                    String feeder = this.getOppositeLineInfo(afterFeederMap, feederDevices.get(0).getFeeder(), midSwitchList);
                    breakerArea.setIsFullLine("0").setStartSwitch(e.getKey()).setOppositeLineId(feeder).setMidSwitch(midSwitchList);
                    return breakerArea;
                }).collect(Collectors.toList());
        return breakerAreaList;
    }

    @Override
    public List<BreakerAreaVO> getDefaultOverviewSwitch(OperationAbnormalityQueryDTO request) {
        List<String> kgPsrTypes = Arrays.asList(DictConstants.KG_PSR_TYPE.split(","));
        // 动态表名切换
        //*ztj ArgTableNameHandler.setArgument(fhzgOrganSuffixMapper.getOrganSuffixByPsrIdOrFeeder(null, request.getFeederId()));
        // 获取开关段信息
        List<FeederDeviceVO> feederDeviceList = fhzgGridOperationAbnormalityMapper.getDefaultBreakerAreaInfo(request.getFeederId(), kgPsrTypes);
        // 根据线路ID分组
        Map<String, List<FeederDeviceVO>> collectMap = feederDeviceList.stream().collect(Collectors.groupingBy(FeederDeviceVO::getFeeder));

        // 获取成图时的开关段和母线的信息（母线的信息需要获取后加入）
        Map<String, List<String>> feederSwitchMap = MapUtil.newHashMap();
        Optional.ofNullable(request.getObjId()).ifPresent(e -> {
            DynamicSvgDirectVO dynamicSvgDirect = fhzgGridOperationAbnormalityMapper.getDistLineDynamicSvgDirectCurrent(e);
            Optional.ofNullable(dynamicSvgDirect).ifPresent(en -> {
                // 动态表名切换
                //*ztj ArgTableNameHandler.setArgument(fhzgOrganSuffixMapper.getOrganSuffixByPsrIdOrFeeder(null, request.getFeederId()));
                List<String> psrIds = en.getKgList().stream().map(FeederSwitchVO::getPsrId).collect(Collectors.toList());
                // 查询topo数据真实的线路信息，如果是联络开关目前暂时不处理，取原图信息
                Map<String, List<FeederSwitchVO>> stringMap = Optional.ofNullable(fhzgGridOperationAbnormalityMapper.getFeederSwitchByPsrId(psrIds))
                        .map(data -> data.stream().collect(Collectors.groupingBy(FeederSwitchVO::getPsrId))).orElse(MapUtil.newHashMap());
                feederSwitchMap.putAll(en.getKgList().stream()
                        .map(data -> {
                            List<FeederSwitchVO> feederSwitchList = stringMap.get(data.getPsrId());
                            if (CollectionUtils.size(feederSwitchList) == 1) { // 这里数量为1时表示非联络开关
                                data.setFeeder(feederSwitchList.get(0).getFeeder());
                            }
                            return data;
                        }).collect(Collectors.groupingBy(FeederSwitchVO::getFeeder, Collectors.mapping(fs -> fs.getPsrId(), Collectors.toList()))));
            });
        });
        // 需要根据成图线路ID获取母线的信息
        List<String> feederList = feederSwitchMap.entrySet().stream()
                .filter(e -> !StringUtils.equals(request.getFeederId(), e.getKey()))
                .map(e -> e.getKey()).collect(Collectors.toList());
        if (ObjectUtils.isNotEmpty(feederList)) {
            // 动态表名切换
            //*ztj ArgTableNameHandler.setArgument(fhzgOrganSuffixMapper.getOrganSuffixByPsrIdOrFeeder(null, request.getFeederId()));
            // 母线转换成线路分组数据
            Map<String, List<FeederDeviceVO>> feederBusbar = Optional.ofNullable(fhzgGridOperationAbnormalityMapper.getFeederSwitchBusbar(feederList))
                    .map(e -> e.stream().collect(Collectors.groupingBy(FeederDeviceVO::getFeeder))).orElse(MapUtil.newHashMap());
            // 开关信息添加母线信息
            feederSwitchMap.forEach((key, subList) -> {
                Optional.ofNullable(feederBusbar.get(key)).ifPresent(en -> subList.addAll(en.stream()
                        .filter(feeder -> subList.contains(feeder.getSwitchId())).map(FeederDeviceVO::getPsrId).collect(Collectors.toList())));
            });
        }

        // 返回值处理
        List<BreakerAreaVO> breakerAreaList = collectMap.entrySet().stream()
                .map(e -> {
                    List<FeederDeviceVO> feederDevices = e.getValue();
                    List<String> endSwitchList = feederDevices.stream()
                            .filter(en -> !StringUtils.equals("-", en.getEndSwitchId()))
                            .map(FeederDeviceVO::getEndSwitchId).collect(Collectors.toList());
                    List<String> midSwitchList = feederDevices.stream()
                            .filter(en -> !StringUtils.equals("-", en.getPsrId()))
                            .map(FeederDeviceVO::getPsrId).collect(Collectors.toList());
                    // 成图对应的显示开关，需要排除结尾开关和已存在的中间开关
                    List<String> switchMxList = Optional.ofNullable(feederSwitchMap.get(e.getKey()))
                            .map(en -> en.stream().filter(s -> !endSwitchList.contains(s) && !midSwitchList.contains(s)).collect(Collectors.toList()))
                            .orElse(Lists.newArrayList());
                    BreakerAreaVO breakerArea = new BreakerAreaVO();
                    breakerArea.setIsFullLine("0").setOppositeLineId(e.getKey())
                            .setEndSwitch(endSwitchList)
                            .setMidSwitch(ListUtils.union(midSwitchList, switchMxList));
                    return breakerArea;
                }).collect(Collectors.toList());

        // 补充逻辑 当返回值不在组内的对侧线路时需要补充对侧线路
        feederSwitchMap.forEach((key, subList) -> {
            if (!StringUtils.equals(request.getFeederId(), key) && ObjectUtils.isEmpty(collectMap.get(key))) {
                BreakerAreaVO breakerArea = new BreakerAreaVO();
                breakerArea.setIsFullLine("0").setOppositeLineId(key).setMidSwitch(subList);
                breakerAreaList.add(breakerArea);
            }
        });
        return breakerAreaList;
    }

    /**
     * 获取转供前后对比数据
     *
     * @param request
     * @return
     */
    @Override
    public AbnormalContrastInfoDTO getContrastInfo(OperationAbnormalityQueryDTO request) {
        AbnormalContrastInfoDTO result = new AbnormalContrastInfoDTO();
        //获取全线路线损对比
        BigDecimal allLineLossBefore = null;
        BigDecimal allLineLossAfter = null;
        LambdaQueryWrapper<FhzgOperationAbnormalityLineLoadfactorLoss> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FhzgOperationAbnormalityLineLoadfactorLoss::getOaId, request.getOaId());
        List<FhzgOperationAbnormalityLineLoadfactorLoss> lineLossList = fhzgLineLoadfactorLossMapper.selectList(lambdaQueryWrapper);
        if (lineLossList != null && !lineLossList.isEmpty()) {
            allLineLossBefore = lineLossList.stream()
                    .map(FhzgOperationAbnormalityLineLoadfactorLoss::getLineLossBefore)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).multiply(new BigDecimal("1000")).setScale(6, RoundingMode.HALF_UP);
            allLineLossAfter = lineLossList.stream()
                    .map(FhzgOperationAbnormalityLineLoadfactorLoss::getLineLossAfter)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).multiply(new BigDecimal("1000")).setScale(6, RoundingMode.HALF_UP);
            //获取负载率对比数据
            Integer overLoadCountBefore = Math.toIntExact(lineLossList.stream().filter(v -> v.getBeforeFactor() != null)
                    .filter(v -> v.getRateCurrent() != null)
                    .filter(a -> a.getBeforeFactor().compareTo(new BigDecimal("100")) > 0).count());
            Integer heavyLoadCountBefore = Math.toIntExact(lineLossList.stream().filter(v -> v.getBeforeFactor() != null)
                    .filter(a -> a.getBeforeFactor().compareTo(new BigDecimal("80")) > 0)
                    .filter(b -> b.getBeforeFactor().compareTo(new BigDecimal("100")) <= 0).count());
            Integer overLoadCountAfter = Math.toIntExact(lineLossList.stream().filter(v -> v.getAfterFactor() != null)
                    .filter(a -> a.getAfterFactor().compareTo(new BigDecimal("100")) > 0).count());
            Integer heavyLoadCountAfter = Math.toIntExact(lineLossList.stream().filter(v -> v.getAfterFactor() != null)
                    .filter(a -> a.getAfterFactor().compareTo(new BigDecimal("80")) > 0)
                    .filter(b -> b.getAfterFactor().compareTo(new BigDecimal("100")) <= 0).count());
            BigDecimal maxLoadBefore = lineLossList.stream().map(FhzgOperationAbnormalityLineLoadfactorLoss::getBeforeFactor)
                    .filter(Objects::nonNull).max(BigDecimal::compareTo).get().setScale(2, RoundingMode.HALF_UP);
            BigDecimal minLoadBefore = lineLossList.stream().map(FhzgOperationAbnormalityLineLoadfactorLoss::getBeforeFactor)
                    .filter(Objects::nonNull).min(BigDecimal::compareTo).get().setScale(2, RoundingMode.HALF_UP);
            BigDecimal maxLoadAfter = lineLossList.stream().map(FhzgOperationAbnormalityLineLoadfactorLoss::getAfterFactor)
                    .filter(Objects::nonNull).max(BigDecimal::compareTo).get().setScale(2, RoundingMode.HALF_UP);
            BigDecimal minLoadAfter = lineLossList.stream().map(FhzgOperationAbnormalityLineLoadfactorLoss::getAfterFactor)
                    .filter(Objects::nonNull).min(BigDecimal::compareTo).get().setScale(2, RoundingMode.HALF_UP);
            result.setLoadRate(AbnormalLoadRateDTO.builder()
                    .heavyLoadLineCountBefore(heavyLoadCountBefore)
                    .heavyLoadLineCountAfter(heavyLoadCountAfter)
                    .overLoadLineCountBefore(overLoadCountBefore)
                    .overLoadLineCountAfter(overLoadCountAfter)
                    .maxLoadRateAfter(maxLoadAfter)
                    .maxLoadRateBefore(maxLoadBefore)
                    .minLoadRateAfter(minLoadAfter)
                    .minLoadRateBefore(minLoadBefore)
                    .countChangeHeavy(heavyLoadCountAfter - heavyLoadCountBefore)
                    .countChangeOver(overLoadCountAfter - overLoadCountBefore)
                    .build());
        }
        result.setLineLoss(AbnormalLineLossDTO.builder().allLineLossAfter(allLineLossAfter)
                .allLineLossBefore(allLineLossBefore)
                .allLineLossChange(allLineLossAfter.compareTo(allLineLossBefore)).build());
        //获取电压对比
        LambdaQueryWrapper<FhzgOperationAbnormalityVoltageViolation> lambdaQueryWrapperVo = new LambdaQueryWrapper<>();
        lambdaQueryWrapperVo.eq(FhzgOperationAbnormalityVoltageViolation::getOaId, request.getOaId());
        List<FhzgOperationAbnormalityVoltageViolation> voltageViolationList = fhzgVoltageViolationMapper.selectList(lambdaQueryWrapperVo);
        if (voltageViolationList != null && !voltageViolationList.isEmpty()) {
            Integer overCountBefore = Math.toIntExact(voltageViolationList.stream().filter(v -> v.getBeforeVoltage() != null)
                    .filter(a -> a.getBeforeVoltage().compareTo(new BigDecimal("10.7")) > 0).count());
            Integer underCountBefore = Math.toIntExact(voltageViolationList.stream().filter(v -> v.getBeforeVoltage() != null)
                    .filter(a -> a.getBeforeVoltage().compareTo(new BigDecimal("9.3")) < 0).count());
            Integer overCountAfter = Math.toIntExact(voltageViolationList.stream().filter(v -> v.getAfterVoltage() != null)
                    .filter(a -> a.getAfterVoltage().compareTo(new BigDecimal("10.7")) > 0).count());
            Integer underCountAfter = Math.toIntExact(voltageViolationList.stream().filter(v -> v.getAfterVoltage() != null)
                    .filter(a -> a.getAfterVoltage().compareTo(new BigDecimal("9.3")) < 0).count());
            BigDecimal maxVoltageBefore = voltageViolationList.stream().map(FhzgOperationAbnormalityVoltageViolation::getBeforeVoltage)
                    .filter(Objects::nonNull).max(BigDecimal::compareTo).get().setScale(2, RoundingMode.HALF_UP);
            BigDecimal minVoltageBefore = voltageViolationList.stream().map(FhzgOperationAbnormalityVoltageViolation::getBeforeVoltage)
                    .filter(Objects::nonNull).min(BigDecimal::compareTo).get().setScale(2, RoundingMode.HALF_UP);
            BigDecimal maxVoltageAfter = voltageViolationList.stream().map(FhzgOperationAbnormalityVoltageViolation::getAfterVoltage)
                    .filter(Objects::nonNull).max(BigDecimal::compareTo).get().setScale(2, RoundingMode.HALF_UP);
            BigDecimal minVoltageAfter = voltageViolationList.stream().map(FhzgOperationAbnormalityVoltageViolation::getAfterVoltage)
                    .filter(Objects::nonNull).min(BigDecimal::compareTo).get().setScale(2, RoundingMode.HALF_UP);
            result.setVoltage(AbnormalVoltageDTO.builder()
                    .minVoltageBefore(minVoltageBefore)
                    .maxVoltageBefore(maxVoltageBefore)
                    .maxVoltageAfter(maxVoltageAfter)
                    .minVoltageAfter(minVoltageAfter)
                    .overVoltageCountBefore(overCountBefore)
                    .overVoltageCountAfter(overCountAfter)
                    .underVoltageCountBefore(underCountBefore)
                    .underVoltageCountAfter(underCountAfter)
                    .overVoltageCountChange(overCountAfter - overCountBefore)
                    .underVoltageCountChange(underCountAfter - underCountBefore).build());
        }
        return result;
    }

    /**
     * 获取运行调优开关pqui数据
     *
     * @param request
     * @return
     */
    @Override
    public List<SwitchDetailDTO> getSvgPquiDataAbnormal(OperationAbnormalityQueryDTO request) {
        List<SwitchDetailDTO> result = new ArrayList<>();
        LambdaQueryWrapper<FhzgOperationAbnormalityTransferAreaResult> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FhzgOperationAbnormalityTransferAreaResult::getOaId, request.getOaId());
        FhzgOperationAbnormalityTransferAreaResult areaResult = transferAreaResultMapper.selectOne(lambdaQueryWrapper);
        Optional.ofNullable(areaResult.getTransferAreaJson())
                .map(e -> JSON.parseObject(e, ApiResponse.class))
                .filter(e -> ObjectUtils.isNotEmpty(e.getData()))
                .map(e -> JSON.parseObject(JSON.toJSONString(e.getData()), ApiAbnormalDataDTO.class))
                .ifPresent(data -> {
                    List<SwitchDetailDTO> list = data.getResult().getSwitchResult().getDetails();
                    result.addAll(list);
                });

        return result;
    }

    /**
     * 获取对侧线路信息数据
     */
    private String getOppositeLineInfo(Map<String, Map<String, List<String>>> afterFeederMap, String lineId, List<String> midSwitchList) {
        // 当带供线路已经是被带供线路时，需要判断带供线路 真实是谁在带供
        Map<String, List<String>> feederMap = afterFeederMap.get(lineId);
        if (ObjectUtils.isNotEmpty(feederMap)) {
            // 已经带供线路时，根据开关交集数量来判断具体应该谁来带
            Set<String> targetSet = Sets.newHashSet(midSwitchList);
            String feederId = feederMap.entrySet().stream()
                    .map(e -> {
                        long interSectionSize = e.getValue().stream().filter(targetSet::contains).count();
                        return new AbstractMap.SimpleEntry<>(e.getKey(), interSectionSize);
                    }) // 取中间开关和带供线路开关的交集数量
                    .reduce((a, b) -> Long.compare(b.getValue(), a.getValue()) > 0 ? b : a)// 比较逻辑，值大的优先，一样的取后者
                    .map(AbstractMap.SimpleEntry::getKey)
                    .orElse(lineId); // 未取到值时，直接取传递过来的线路信息
            return feederId;
        }
        return lineId; // 当带供线路不是被带供线路时，直接返回对线线路信息
    }

}
