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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
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.Lists;
import com.hdkj.hussar.ApiResponse;
import com.hdkj.lt.base.exception.BusinessException;
import com.hdkj.lt.bf.entity.FhzgPlanPowerCut;
import com.hdkj.lt.bf.entity.dto.CreatePlanPowerCutDTO;
import com.hdkj.lt.bf.entity.dto.FhzgPlanDistMappingFileDTO;
import com.hdkj.lt.bf.entity.dto.HasDataTagDTO;
import com.hdkj.lt.bf.entity.dto.TopoDTO;
import com.hdkj.lt.bf.entity.vo.FhzgPlanPowerCutVO;
import com.hdkj.lt.bf.mapper.FhzgPlanAwaitTransferUsersMapper;
import com.hdkj.lt.bf.mapper.FhzgPlanDistMappingFileMapper;
import com.hdkj.lt.bf.mapper.FhzgPlanPowerCutMapper;
import com.hdkj.lt.bf.mapper.FhzgPlanSwitchInfoListMapper;
import com.hdkj.lt.bf.service.*;
import com.hdkj.lt.bf.service.aspect.UserCountyCodeAuto;
import com.hdkj.lt.core.bizms.modle.dto.FhzgDistCustomerDTO;
import com.hdkj.lt.core.bizms.modle.dto.FhzgPlanAwaitTransferUsersCountDTO;
import com.hdkj.lt.core.bizms.modle.po.plan.*;
import com.hdkj.lt.core.sys.dao.SysDictMapper;
import com.hdkj.lt.core.sys.model.po.DicSingle;
import com.hdkj.lt.feign.IPlanCreateClient;
import com.hdkj.lt.modle.dto.jsty.AllSwitchInfoListDTO;
import com.hdkj.lt.modle.dto.plan.PlanCreateSwitchDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 计划停电转供方案信息表 服务实现类
 *
 * @author zhousc
 * @since 2025-05-07
 */
@Service
@Slf4j
public class FhzgPlanPowerCutServiceImpl extends ServiceImpl<FhzgPlanPowerCutMapper, FhzgPlanPowerCut> implements FhzgPlanPowerCutService {

    @Autowired
    FhzgPlanDistMappingFileMapper fhzgPlanDistMappingFileMapper;

    @Autowired
    FhzgPlanAwaitTransferUsersMapper fhzgPlanAwaitTransferUsersMapper;

    @Autowired
    FhzgPlanPowerCutPvUsersService fhzgPlanPowerCutPvUsersService;

    @Autowired
    FhzgPlanAwaitTransferSwitchSectionService awaitTransferSwitchSectionServices;

    @Autowired
    FhzgPlanOppositeLineCarryCapacityService oppositeLineCarryCapacityService;

    @Autowired
    FhzgPlanTransferSchemeService fhzgPlanTransferSchemeService;
    @Autowired
    FhzgPlanSwitchInfoListMapper switchInfoListMapper;

    @Autowired
    IPlanCreateClient planCreateClient;

    @Autowired
    SysDictMapper sysDictMapper;

    private static final String PLAN_STATE = "plan_state";


    @Override
    @UserCountyCodeAuto(sourceFiled = "countyCode", targetFiled = "countyCodeList")
    public Page<FhzgPlanPowerCutVO> getSchemeList(FhzgPlanPowerCut obj) {
        Page<FhzgPlanPowerCutVO> page = new Page<>();
        page.setCurrent(obj.getPageNum());
        page.setSize(obj.getPageSize());
        LambdaQueryWrapper<FhzgPlanPowerCutVO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotEmpty(obj.getSchemeState()), FhzgPlanPowerCut::getSchemeState, obj.getSchemeState())
                .eq(StringUtils.isNotEmpty(obj.getPlanSource()),FhzgPlanPowerCut::getPlanSource,obj.getPlanSource())
                .eq(StringUtils.isNotEmpty(obj.getPlanState()), FhzgPlanPowerCut::getPlanState, obj.getPlanState())
                .eq(obj.getCountyCode() != null, FhzgPlanPowerCut::getCountyCode, obj.getCountyCode())
                .in(CollUtil.isNotEmpty(obj.getCountyCodeList()), FhzgPlanPowerCut::getCountyCode, obj.getCountyCodeList())
                .like(StringUtils.isNotEmpty(obj.getLineName()), FhzgPlanPowerCut::getLineName, obj.getLineName())
                .gt(obj.getPlanStartTime() != null, FhzgPlanPowerCut::getPlanStartTime, obj.getPlanStartTime())
                .le(obj.getPlanEndTime() != null, FhzgPlanPowerCut::getPlanStartTime, obj.getPlanEndTime())//页面查询开始，结束时间，针对查询的是计划的开始时间
                .eq(FhzgPlanPowerCut::getIsNewest, "1")//计划列表默认查询最新的数据
                .and(w -> w.ne(FhzgPlanPowerCut::getIsDelete, "1").or().isNull(FhzgPlanPowerCut::getIsDelete))//查询不为 删除的数据,或者为null
                .like(StringUtils.isNotEmpty(obj.getPlanNo()), FhzgPlanPowerCut::getPlanNo, obj.getPlanNo())//查询条件新增plan_no
                .last(" ORDER BY ABS(TIMESTAMPDIFF(SECOND,PLAN_START_TIME,NOW())) ASC ,id desc");
        List<FhzgPlanPowerCutVO> list = baseMapper.selectSchemeList(page, wrapper);

        if (CollUtil.isNotEmpty(list)) {
            //查询计划对应的线路图信息
            List<Long> idList = list.stream().map(FhzgPlanPowerCutVO::getId).collect(Collectors.toList());
            List<FhzgPlanDistMappingFileDTO> fileList = fhzgPlanDistMappingFileMapper.getMappingFileByPlanId(idList);
            if (CollUtil.isNotEmpty(fileList)) {
                Map<Long, List<FhzgPlanDistMappingFileDTO>> fileListMap = fileList.stream().collect(Collectors.groupingBy(FhzgPlanDistMappingFileDTO::getPlanId));
                list.forEach(e -> {
                    e.setFileList(fileListMap.get(e.getId()));
                });
            } else {
                log.info("未查询到计划文件列表planIdList:{}", idList);
            }
            //查询统计，用户数量，重要用户数量，敏感用户数量，用户负荷
            List<FhzgPlanAwaitTransferUsersCountDTO> usersCountDTOList = fhzgPlanAwaitTransferUsersMapper.selectAwaitUserCountByPlanId(idList);
            if (CollUtil.isNotEmpty(usersCountDTOList)) {
                Map<Long, FhzgPlanAwaitTransferUsersCountDTO> fusersCountMap = usersCountDTOList.stream().collect(Collectors.toMap(FhzgPlanAwaitTransferUsersCountDTO::getPlanId, Function.identity(), (k1, k2) -> k2));
                list.forEach(e -> {
                    FhzgPlanAwaitTransferUsersCountDTO userCountDTO = fusersCountMap.get(e.getId());
                    if (!Objects.isNull(userCountDTO)) {
                        e.setTransferCriticalUsers(userCountDTO.getTransferCriticalUsers());//重要用户数量
                        e.setTransferSensitiveUsers(userCountDTO.getTransferSensitiveUsers());//敏感用户
                        e.setUserCount(userCountDTO.getUserCount());//用户数量
                        e.setUserLoads(userCountDTO.getUserLoads());//用户负荷
                        e.setProtectUsers(userCountDTO.getProtectUsers());//保电用户数量
                    }
                });
            } else {
                log.info("未查询到待转供用户数量planIdList:{}", idList);
            }
            //查询停电计划对应的光伏用户数量
            List<FhzgPlanPowerCutPvUsers> countCutPvUsers = fhzgPlanPowerCutPvUsersService.countByPlanId(idList);
            if (CollUtil.isNotEmpty(countCutPvUsers)) {
                Map<Long, FhzgPlanPowerCutPvUsers> cutPvUsersMap = countCutPvUsers.stream().collect(Collectors.toMap(FhzgPlanPowerCutPvUsers::getPlanId, Function.identity(), (k1, k2) -> k2));
                list.forEach(e -> {
                    FhzgPlanPowerCutPvUsers fhzgPlanPowerCutPvUsers = cutPvUsersMap.get(e.getId());
                    Integer count = Objects.isNull(fhzgPlanPowerCutPvUsers) ? 0 : Objects.isNull(fhzgPlanPowerCutPvUsers.getCount()) ? 0 : fhzgPlanPowerCutPvUsers.getCount();
                    e.setPvUsers(count);
                });
            } else {
                log.info("未查询到光伏用户数量planIdList:{}", idList);
            }
            List<DicSingle> dicSingleList = sysDictMapper.getDictSingleByTypeName(PLAN_STATE);
            Map<String,String> dicMap = new HashMap<>();
            if (CollUtil.isNotEmpty(dicSingleList)) {
                dicMap = dicSingleList.stream().collect(Collectors.toMap(DicSingle::getValue, DicSingle::getLabel));
            }
            //枚举值转换
            Map<String, String> finalDicMap = dicMap;
            list.forEach(e -> {
                String label = finalDicMap.get(e.getPlanState());
                e.setPlanState(label == null ? e.getPlanState() : label);
            });
            //设置历史版本数据列表
            List<String> planNoList = list.stream().map(FhzgPlanPowerCutVO::getPlanNo).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(planNoList)) {
                List<FhzgPlanPowerCut> cutList = queryHistListBatch(planNoList);
                Map<String, List<FhzgPlanPowerCut>> cutMap = cutList.stream().collect(Collectors.groupingBy(FhzgPlanPowerCut::getPlanNo));
                list.forEach(e -> e.setHistList(cutMap.get(e.getPlanNo())));
            }

        } else {
            log.info("查询计划数据为空condition:{}", obj);
        }
        list.stream().filter(i -> i.getUserLoads() != null).forEach(i -> i.setUserLoads(i.getUserLoads().multiply(new BigDecimal("1000"))));
        return page.setRecords(list);
    }


    /**
     * @author luorui
     * @date 2025/5/20 14:10
     * @discription 根据计划id 查询停电计划详情
     **/
    @Override
    public FhzgPlanPowerCutVO getSchemeByPlanId(Long planId) {
        FhzgPlanPowerCutVO fhzgPlanPowerCutVO = baseMapper.getSchemeByPlanId(planId);
        return fhzgPlanPowerCutVO;
    }

    /**
     * @author luorui
     * @date 2025/5/21 17:09
     * @discription 更新方案状态
     **/
    @Override
    public Integer updateSchemeState(FhzgPlanPowerCut obj) {
        if (Objects.isNull(obj.getId())) {
            throw new BusinessException("更新方案主键为空");
        }
        if (StrUtil.isBlank(obj.getSchemeState())) {
            throw new BusinessException("更新方案字段为空");
        }
        return baseMapper.updateSchemeState(obj);
    }


    /**
     * 查询计划下，转供范围，转供计划，转供评分是否有数据，返回给前端禁用按钮
     *
     * @author luorui
     * @date 2025/5/27 10:36
     **/
    @Override
    public HasDataTagDTO getHasDataTag(FhzgDistCustomerDTO dto) {
        Long planId = dto.getPlanId();
        if (Objects.isNull(planId)) {
            throw new BusinessException("查询参数planId为空");
        }
        HasDataTagDTO hasDataTagDTO = new HasDataTagDTO();
        Boolean transferAreaTag = false;
        Boolean transferSchemeTag = false;
        Boolean transferScoreTag = false;
        //查询转供范围下是否有数据，待转供用户，待转供开关段，对侧承载力分析 都没有数据则为false
        LambdaQueryWrapper<FhzgPlanAwaitTransferUsers> awaitTransferUsersWrapper = new LambdaQueryWrapper<>();
        awaitTransferUsersWrapper.eq(FhzgPlanAwaitTransferUsers::getPlanId, planId);
        Long countAwaitTransferUsers = fhzgPlanAwaitTransferUsersMapper.selectCount(awaitTransferUsersWrapper);
        if (countAwaitTransferUsers != null && countAwaitTransferUsers.compareTo(0L) > 0) {
            transferAreaTag = true;
        }
        if (!transferAreaTag) {
            LambdaQueryWrapper<FhzgPlanAwaitTransferSwitchSection> awaitTransferSwitchWrapper = new LambdaQueryWrapper<>();
            awaitTransferSwitchWrapper.eq(FhzgPlanAwaitTransferSwitchSection::getPlanId, planId);
            Long countAwaitTransferSwitch = awaitTransferSwitchSectionServices.count(awaitTransferSwitchWrapper);
            if (countAwaitTransferSwitch != null && countAwaitTransferSwitch.compareTo(0L) > 0) {
                transferAreaTag = true;
            }
        }
        if (!transferAreaTag) {
            LambdaQueryWrapper<FhzgPlanOppositeLineCarryCapacity> oppositeLineCarryWrapper = new LambdaQueryWrapper<>();
            oppositeLineCarryWrapper.eq(FhzgPlanOppositeLineCarryCapacity::getPlanId, planId);
            Long countOppositeLineCarry = oppositeLineCarryCapacityService.count(oppositeLineCarryWrapper);
            if (countOppositeLineCarry != null && countOppositeLineCarry.compareTo(0L) > 0) {
                transferAreaTag = true;
            }
        }
        //查询转供方案是否有数据  转供方案是否有数据   //查询转供方案评分是否有数据 评分指标结果 和 评分细则都没数据则不显示
        LambdaQueryWrapper<FhzgPlanTransferScheme> schemeWrapper = new LambdaQueryWrapper<>();
        schemeWrapper.eq(FhzgPlanTransferScheme::getPlanId, planId);
        Long countScheme = fhzgPlanTransferSchemeService.count(schemeWrapper);
        if (countScheme != null && countScheme.compareTo(0L) > 0) {
            transferSchemeTag = true;
            transferScoreTag = true;
        }
        hasDataTagDTO.setTransferAreaTag(transferAreaTag);
        hasDataTagDTO.setTransferSchemeTag(transferSchemeTag);
        hasDataTagDTO.setTransferScoreTag(transferScoreTag);
        log.info("返回前端标识,transferAreaTag:{},transferSchemeTag:{},:transferScoreTag:{}", transferAreaTag, transferSchemeTag, transferScoreTag);
        return hasDataTagDTO;
    }

    /**
     * @author luorui
     * @date 2025/6/28 15:45
     * @discription 查询单条计划信息
     **/
    @Override
    public FhzgPlanPowerCutVO getByPlanIdOrPlanNo(FhzgDistCustomerDTO dto) {
        Long planId = dto.getPlanId();
        String planNo = dto.getPlanNo();
        FhzgPlanPowerCut fhzgPlanPowerCut = null;
        List<FhzgPlanPowerCut> cutHistList = new ArrayList<>();//查询planNo下所有计划
        //优先根据planId 查询
        if (!Objects.isNull(planId)) {
            fhzgPlanPowerCut = this.getSchemeByPlanId(planId);
        } else {
            if (StrUtil.isBlank(planNo)) {
                throw new BusinessException("请求参数planNo为空");
            }
            cutHistList = queryHistList(planNo);
            //根据planNo查询的话默认查询 最新的计划数据
            for (FhzgPlanPowerCut planPowerCut : cutHistList) {
                if (Objects.equals(planPowerCut.getIsNewest(), 1)) {
                    fhzgPlanPowerCut = planPowerCut;
                    break;
                }
            }
        }
        if (Objects.isNull(fhzgPlanPowerCut)) {
            return null;
        }
        FhzgPlanPowerCutVO fhzgPlanPowerCutVO = new FhzgPlanPowerCutVO();
        BeanUtil.copyProperties(fhzgPlanPowerCut, fhzgPlanPowerCutVO);
        //查询计划对应的线路图信息
        List<Long> idList = Lists.newArrayList();
        idList.add(fhzgPlanPowerCut.getId());
        List<FhzgPlanDistMappingFileDTO> fileList = fhzgPlanDistMappingFileMapper.getMappingFileByPlanId(idList);
        if (CollUtil.isNotEmpty(fileList)) {
            Map<Long, List<FhzgPlanDistMappingFileDTO>> fileListMap = fileList.stream().collect(Collectors.groupingBy(FhzgPlanDistMappingFileDTO::getPlanId));
            fhzgPlanPowerCutVO.setFileList(fileListMap.get(fhzgPlanPowerCutVO.getId()));
        } else {
            log.info("未查询到计划文件列表planIdList:{}", idList);
        }
        //查询统计，用户数量，重要用户数量，敏感用户数量，用户负荷
        List<FhzgPlanAwaitTransferUsersCountDTO> usersCountDTOList = fhzgPlanAwaitTransferUsersMapper.selectAwaitUserCountByPlanId(idList);
        if (CollUtil.isNotEmpty(usersCountDTOList)) {
            Map<Long, FhzgPlanAwaitTransferUsersCountDTO> fusersCountMap = usersCountDTOList.stream().collect(Collectors.toMap(FhzgPlanAwaitTransferUsersCountDTO::getPlanId, Function.identity(), (k1, k2) -> k2));

            FhzgPlanAwaitTransferUsersCountDTO userCountDTO = fusersCountMap.get(fhzgPlanPowerCutVO.getId());
            if (!Objects.isNull(userCountDTO)) {
                fhzgPlanPowerCutVO.setTransferCriticalUsers(userCountDTO.getTransferCriticalUsers());//重要用户数量
                fhzgPlanPowerCutVO.setTransferSensitiveUsers(userCountDTO.getTransferSensitiveUsers());//敏感用户
                fhzgPlanPowerCutVO.setUserCount(userCountDTO.getUserCount());//用户数量
                fhzgPlanPowerCutVO.setUserLoads(userCountDTO.getUserLoads().multiply(new BigDecimal("1000")));//用户负荷
                fhzgPlanPowerCutVO.setProtectUsers(userCountDTO.getProtectUsers());//保电用户数量
            }

        } else {
            log.info("未查询到待转供用户数量planIdList:{}", idList);
        }
        //查询停电计划对应的光伏用户数量
        List<FhzgPlanPowerCutPvUsers> countCutPvUsers = fhzgPlanPowerCutPvUsersService.countByPlanId(idList);
        if (CollUtil.isNotEmpty(countCutPvUsers)) {
            Map<Long, FhzgPlanPowerCutPvUsers> cutPvUsersMap = countCutPvUsers.stream().collect(Collectors.toMap(FhzgPlanPowerCutPvUsers::getPlanId, Function.identity(), (k1, k2) -> k2));

            FhzgPlanPowerCutPvUsers fhzgPlanPowerCutPvUsers = cutPvUsersMap.get(fhzgPlanPowerCutVO.getId());
            Integer count = Objects.isNull(fhzgPlanPowerCutPvUsers) ? 0 : Objects.isNull(fhzgPlanPowerCutPvUsers.getCount()) ? 0 : fhzgPlanPowerCutPvUsers.getCount();
            fhzgPlanPowerCutVO.setPvUsers(count);

        } else {
            log.info("未查询到光伏用户数量planIdList:{}", idList);
        }
        List<DicSingle> dicSingleList = sysDictMapper.getDictSingleByTypeName(PLAN_STATE);
        Map<String,String> dicMap = new HashMap<>();
        if (CollUtil.isNotEmpty(dicSingleList)) {
            dicMap = dicSingleList.stream().collect(Collectors.toMap(DicSingle::getValue, DicSingle::getLabel));
        }
        //枚举值转换
        String label = dicMap.get(fhzgPlanPowerCutVO.getPlanState());
        fhzgPlanPowerCutVO.setPlanState(label == null ? fhzgPlanPowerCutVO.getPlanState() : label);
        //设置历史版本数据列表
        if (CollUtil.isNotEmpty(cutHistList)) {
            fhzgPlanPowerCutVO.setHistList(cutHistList);
        } else {
            cutHistList = queryHistList(fhzgPlanPowerCut.getPlanNo());
            fhzgPlanPowerCutVO.setHistList(cutHistList);
        }
        return fhzgPlanPowerCutVO;
    }

    private List<FhzgPlanPowerCut> queryHistList(String planNo) {
        LambdaQueryWrapper<FhzgPlanPowerCut> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FhzgPlanPowerCut::getPlanNo, planNo)
                .orderByDesc(FhzgPlanPowerCut::getCreateTime)
                .last("LIMIT 3");
        setQueryColumn(queryWrapper);
        List<FhzgPlanPowerCut> cutHistList = baseMapper.selectList(queryWrapper);
        cutHistList.forEach(i -> i.setPlanCreateTime(baseMapper.getPlanCreateTimeByPlanId(i.getId())));
        return cutHistList;
    }

    private List<FhzgPlanPowerCut> queryHistListBatch(List<String> planNoList) {
        List<FhzgPlanPowerCut> cutHistList = baseMapper.queryHistListBatch(planNoList);
        cutHistList.forEach(i -> i.setPlanCreateTime(baseMapper.getPlanCreateTimeByPlanId(i.getId())));
        return cutHistList;
    }

    private void setQueryColumn(LambdaQueryWrapper<FhzgPlanPowerCut> queryWrapper) {
        queryWrapper.select(FhzgPlanPowerCut::getId, FhzgPlanPowerCut::getPlanNo, FhzgPlanPowerCut::getPlanStartTime,
                FhzgPlanPowerCut::getPlanEndTime, FhzgPlanPowerCut::getLineId, FhzgPlanPowerCut::getLineName,
                FhzgPlanPowerCut::getLineContent, FhzgPlanPowerCut::getWorkContent, FhzgPlanPowerCut::getFeederName,
                FhzgPlanPowerCut::getCityCode, FhzgPlanPowerCut::getCityName, FhzgPlanPowerCut::getPlanState,
                FhzgPlanPowerCut::getSchemeState, FhzgPlanPowerCut::getPowerOnSuccess, FhzgPlanPowerCut::getCreator,
                FhzgPlanPowerCut::getCreateTime, FhzgPlanPowerCut::getLastEditor, FhzgPlanPowerCut::getLastTime,
                FhzgPlanPowerCut::getIsNewest, FhzgPlanPowerCut::getCountyCode,
                FhzgPlanPowerCut::getCountyName);
    }

    @Override
    public List<AllSwitchInfoListDTO> getAllSwitchBySchemeId(Long planId) {
        LambdaQueryWrapper<FhzgPlanSwitchInfoList> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FhzgPlanSwitchInfoList::getPlanId, planId);
        FhzgPlanSwitchInfoList planSwitchInfoList = switchInfoListMapper.selectOne(lambdaQueryWrapper);
        //FhzgPlanPowerCut fhzgPlanPowerCut = baseMapper.selectById(planId);
        String allSwitchInfoListJson = planSwitchInfoList.getAllSwitchInfoListJson();
        return JSON.parseArray(allSwitchInfoListJson, AllSwitchInfoListDTO.class);
    }

    @Override
    public ApiResponse<Boolean> createPlanPowerCut(CreatePlanPowerCutDTO createPlanPowerCutDTO) {
        PlanCreateSwitchDTO planCreateSwitchDTO = new PlanCreateSwitchDTO();
        planCreateSwitchDTO.setStartSwitchId(createPlanPowerCutDTO.getStartSwitchId());
        planCreateSwitchDTO.setEndSwitchID(createPlanPowerCutDTO.getEndSwitchID());
        planCreateSwitchDTO.setFeederId(createPlanPowerCutDTO.getFeederId());
        planCreateSwitchDTO.setWorkContent(createPlanPowerCutDTO.getWorkContent());
        planCreateSwitchDTO.setFeederName(createPlanPowerCutDTO.getFeederName());
        planCreateSwitchDTO.setStartTime(createPlanPowerCutDTO.getStartTime());
        planCreateSwitchDTO.setEndTime(createPlanPowerCutDTO.getEndTime());

        if("01".equals(createPlanPowerCutDTO.getType())){
            //仅校验是否形成封闭停电范围
            Boolean checkPowerOutArea = planCreateClient.checkPowerOutArea(planCreateSwitchDTO);
            if(!checkPowerOutArea){
                return ApiResponse.fail("所选择开关未形成封闭区域，请重新选择");
            }
        }else if("02".equals(createPlanPowerCutDTO.getType())){
            //创建计划停电
            planCreateClient.createPlanPowerCut(planCreateSwitchDTO);
        }
        return ApiResponse.success();
    }

    private boolean canReachAllDownstreams(
            String upstream,
            List<String> downstreams,
            Map<String, TopoDTO> topoMap) {

        Map<String, String> childToParent = buildChildToParentMap(topoMap);

        for (String downstream : downstreams) {
            if (!isReachable(upstream, downstream, childToParent)) {
                return false;
            }
        }
        return true;
    }

    // 构建子节点到父节点的映射
    private Map<String, String> buildChildToParentMap(Map<String, TopoDTO> topoMap) {
        Map<String, String> map = new HashMap<>();
        for (TopoDTO topo : topoMap.values()) {
            if (topo.getPid() != null) {
                map.put(topo.getPsrId(), topo.getPid());
            }
        }
        return map;
    }

    // 检查节点是否可达（从下游向上追溯）
    private boolean isReachable(String upstream, String node, Map<String, String> childToParent) {
        String current = node;
        while (current != null && !current.equals(upstream)) {
            current = childToParent.get(current);
        }
        return current != null;
    }

}
