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

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hdkj.hussar.ApiResponse;
import com.hdkj.lt.base.constants.CommonConstant;
import com.hdkj.lt.base.constants.DictConstants;
import com.hdkj.lt.base.enums.CommonUnitEnum;
import com.hdkj.lt.base.exception.ExceptionCast;
import com.hdkj.lt.bf.adapter.SiStateEstimationClient;
import com.hdkj.lt.bf.entity.FhzgPlanPowerCut;
import com.hdkj.lt.bf.entity.dto.BeakerStatusDTO;
import com.hdkj.lt.bf.entity.dto.FhzgPlanTransferSchemeDTO;
import com.hdkj.lt.bf.entity.dto.SwitchOrTransformerDTO;
import com.hdkj.lt.bf.entity.dto.TopoDTO;
import com.hdkj.lt.bf.entity.vo.*;
import com.hdkj.lt.bf.mapper.*;
import com.hdkj.lt.bf.service.*;
import com.hdkj.lt.core.bizms.modle.dto.StateEstimation;
import com.hdkj.lt.core.bizms.modle.po.DwdShbDsFeederBase;
import com.hdkj.lt.core.bizms.modle.po.FeederTopo;
import com.hdkj.lt.core.bizms.modle.po.FhzgSwitchProtectionSettings;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultPowerCut;
import com.hdkj.lt.core.bizms.modle.po.plan.FhzgInfoBreakerSvgAfter;
import com.hdkj.lt.core.bizms.modle.po.plan.FhzgPlanTransferScheme;
import com.hdkj.lt.core.bizms.modle.request.StateEstimationEquipRequest;
import com.hdkj.lt.core.bizms.modle.request.StateEstimationRequest;
import com.hdkj.lt.core.plugins.thread.MultiThreadExecuteService;
import com.hdkj.lt.core.sys.dao.DwdShbDsFeederBaseMapper;
import com.hdkj.lt.core.sys.dao.FhzgOrganSuffixMapper;
import com.hdkj.lt.core.sys.service.DwdShbDsFeederBaseService;
import com.hdkj.lt.core.sys.service.SwitchProtectionSettingsService;
import com.hdkj.lt.feign.IStateEstimationApiClient;
import com.hdkj.lt.modle.dto.jsty.AllSwitchInfoDTO;
import com.hdkj.lt.modle.dto.jsty.AllSwitchInfoListDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class FhzgSvgBreakersServiceImpl implements FhzgSvgBreakersService {

    private final FeederTopoMapper feederTopoMapper;

    private final DwdShbDsFeederBaseService dwdShbDsFeederBaseService;

    private final DwdShbDsFeederBaseMapper dwdshbDsFeederBaseMapper;

    private final SwitchProtectionSettingsService fhzgSwitchProtectionSettingsService;

    private final SiStateEstimationClient siStateEstimationClient;

    private final FhzgPlanTransferSchemeMapper fhzgPlanTransferSchemeMapper;

    private final FhzgInfoBreakerSvgAfterMapper fhzgInfoBreakerSvgAfterMapper;

    private final IStateEstimationApiClient iStateEstimationApiClient;

    private final FhzgOrganSuffixMapper fhzgOrganSuffixMapper;

    private final FhzgPlanPowerCutService planPowerCutService;

    private final FaultPowerCutMapper faultPowerCutMapper;
    private final IFaultPowerCutService faultPowerCutService;
    private final DwdShbDsSwitchBaseMapper dwdShbDsSwitchBaseMapper;

    private final FhzgPlanTransferSchemeService planTransferSchemeService;

    private final IFaultTransferSchemeService faultTransferSchemeService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    MultiThreadExecuteService multiThreadExecuteService;


    private static final DateTimeFormatter TIME_FORMATTER =
            DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
    private static final ThreadLocal<SimpleDateFormat> sdf =
            ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

    @Override
    public List<BeakerSvgInfoVO> getBreakerStatusInfo(BeakerStatusDTO dto) {
        List<BeakerSvgInfoVO> beakerStatusInfoVOS = new ArrayList<>();

        DwdShbDsFeederBase dwdShbDsFeederBase = dwdShbDsFeederBaseService.getByPsrId(dto.getLinePsrId());
        if (ObjectUtil.isNull(dwdShbDsFeederBase)) {
            ExceptionCast.cast("线路不存在");
        }
        lcZgBgs(dto, dwdShbDsFeederBase, beakerStatusInfoVOS);
        log.info("开关状态：" + JSON.toJSONString(beakerStatusInfoVOS));

        if (StringUtils.isNotEmpty(dto.getPlanId()) || StringUtils.isNotEmpty(dto.getSchemeId())) {
            // 转供后的逻辑
            String schemeId = dto.getSchemeId();
            FhzgPlanTransferScheme fhzgPlanTransferScheme = new FhzgPlanTransferScheme();
            if (StringUtils.isEmpty(dto.getSchemeId())) {
                fhzgPlanTransferScheme.setPlanId(Long.valueOf(dto.getPlanId()));
                fhzgPlanTransferScheme.setSchemeState("01");
                List<FhzgPlanTransferSchemeDTO> fhzgPlanTransferSchemeByPlanId = fhzgPlanTransferSchemeMapper.getFhzgPlanTransferSchemeByPlanId(fhzgPlanTransferScheme);
                if (!fhzgPlanTransferSchemeByPlanId.isEmpty()) {
                    schemeId = String.valueOf(fhzgPlanTransferSchemeByPlanId.get(0).getId());
                }
            }
            if (StringUtils.isNotEmpty(schemeId)) {
                LambdaQueryWrapper<FhzgInfoBreakerSvgAfter> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(FhzgInfoBreakerSvgAfter::getSchemeId, Long.valueOf(schemeId));
                List<FhzgInfoBreakerSvgAfter> fhzgInfoBreakerSvgAfters = fhzgInfoBreakerSvgAfterMapper.selectList(wrapper);
                fhzgInfoBreakerSvgAfters.stream().forEach(o ->
                {
                    for (BeakerSvgInfoVO beakerStatusInfoVO : beakerStatusInfoVOS) {
                        if (beakerStatusInfoVO.getBreakerPsrId().equals(o.getStartSwitchId())) {
                            beakerStatusInfoVO.setZghs(BeakerStatusInfoVO.builder()
                                    .breakerPsrId(o.getStartSwitchId())
                                    .punit(CommonUnitEnum.P.getCode())
                                    .qunit(CommonUnitEnum.Q.getCode())
                                    .iunit(CommonUnitEnum.I.getCode())
                                    .uunit(CommonUnitEnum.U.getCode())
                                    .pvalue(Optional.ofNullable(convertToKW(o.getAfterP())).map(String::valueOf).orElse(null))
                                    .qvalue(Optional.ofNullable(o.getAfterQ()).map(String::valueOf).orElse(null))
                                    .ivalue(Optional.ofNullable(o.getAfterI()).map(String::valueOf).orElse(null))
                                    .build());
                        }
                    }
                });
            }
        }

        return beakerStatusInfoVOS;
    }

    private void lcZgBgs(BeakerStatusDTO dto, DwdShbDsFeederBase dwdShbDsFeederBase, List<BeakerSvgInfoVO> beakerStatusInfoVOS) {
        // 所有开关
        List<FeederTopo> feederTopos = getFeederTopos(dwdShbDsFeederBase);
        // 调用状态估算
        List<StateEstimation.StateEstimationSwitchResult> periodSwitchSeResult = new ArrayList<>();
        try {
            List<StateEstimation.StateEstimationSwitchResult> ss = new ArrayList<>();
            StateEstimation s = JSON.parseObject(JSON.toJSONString(redisTemplate.opsForValue().get(dto.getLinePsrId() + getStartOfDay(dto.getTime()))), StateEstimation.class);
            if (s != null) {
                log.info(JSON.toJSONString(ss));
                ss = s.getPeriodSwitchSeResult();
                String a = ss.get(0).getSeiStatuss().get(getDataByTimeSlot(dto.getTime()));
                String b = ss.get(0).getSeoStatuss().get(getDataByTimeSlot(dto.getTime()));
                List<String> seiStatuss = new ArrayList<>();
                List<String> seoStatuss = new ArrayList<>();
                seiStatuss.add(a);
                seoStatuss.add(b);
                ss.get(0).setSeiStatuss(seiStatuss);
                ss.get(0).setSeoStatuss(seoStatuss);
            } else {
                ss = siStateEstimationClient.queryPeriodByFeeder(StateEstimationRequest.builder()
                        .psrIds(Arrays.asList(dto.getLinePsrId()))
                        .containerCode(Arrays.asList(CommonConstant.SWITCH))
                        .startTime(dto.getTime())
                        .endTime(dto.getTime())
                        .isAuto(Boolean.FALSE)
                        .build()).getData().getPeriodSwitchSeResult();
            }
            if (CollectionUtils.isNotEmpty(ss)) {
                periodSwitchSeResult.addAll(ss);
            }
            log.info("状估开关：" + periodSwitchSeResult.size());
            log.info("所有开关：" + feederTopos.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 保供
        LambdaQueryWrapper<FhzgSwitchProtectionSettings> wrapper = new LambdaQueryWrapper();
        wrapper.eq(FhzgSwitchProtectionSettings::getParentLinePsrId, dwdShbDsFeederBase.getPsrId());
        List<FhzgSwitchProtectionSettings> fhzgSwitchProtectionSettings = fhzgSwitchProtectionSettingsService.list(wrapper);
        log.info("保供开关值：" + fhzgSwitchProtectionSettings.size());
        feederTopos.stream().forEach(o ->
        {
            BeakerSvgInfoVO beakerSvgInfoVO = BeakerSvgInfoVO.builder().breakerPsrId(o.getPsrId()).build();
            if (CollectionUtils.isNotEmpty(periodSwitchSeResult)) {
                periodSwitchSeResult.stream().forEach(e -> {
                    if (o.getPsrId().equals(e.getPsrId())) {
                        String seiIs = "0.0";
                        String seoIs = "0.0";
                        try {
                            if (StringUtils.isNotEmpty(e.getSeiIs().get(0))) {
                                BigDecimal bigDecimal = new BigDecimal(e.getSeiIs().get(0));
                                seiIs = bigDecimal.multiply(new BigDecimal(1000)).toString();
                            }
                            if (StringUtils.isNotEmpty(e.getSeoIs().get(0))) {
                                BigDecimal bigDecimal = new BigDecimal(e.getSeoIs().get(0));
                                seoIs = bigDecimal.multiply(new BigDecimal(1000)).toString();
                            }
                        } catch (Exception exception) {
                            exception.printStackTrace();
                        }
                        beakerSvgInfoVO.setLcs(BeakerStatusInfoVO.builder()
                                .breakerPsrId(o.getPsrId())
                                .punit(CommonUnitEnum.P.getCode())
                                .qunit(CommonUnitEnum.Q.getCode())
                                .iunit(CommonUnitEnum.I.getCode())
                                .uunit(CommonUnitEnum.U.getCode())
                                .pvalue(convertToKW(e.getSeiPs().get(0)))
                                .qvalue(e.getSeiQs().get(0))
                                .ivalue(seiIs)
                                .uvalue(e.getSeiUs().get(0))
                                .status(e.getSeiStatuss().get(0))
                                .build());

                        beakerSvgInfoVO.setZgs(BeakerStatusInfoVO.builder()
                                .breakerPsrId(o.getPsrId())
                                .punit(CommonUnitEnum.P.getCode())
                                .qunit(CommonUnitEnum.Q.getCode())
                                .iunit(CommonUnitEnum.I.getCode())
                                .uunit(CommonUnitEnum.U.getCode())
                                .pvalue(convertToKW(e.getSeoPs().get(0)))
                                .qvalue(e.getSeoQs().get(0))
                                .ivalue(seoIs)
                                .uvalue(e.getSeoUs().get(0))
                                .status(e.getSeoStatuss().get(0))
                                .build());
                    }
                });
            }
            fhzgSwitchProtectionSettings.stream().forEach(e -> {
                if (o.getPsrId().equals(e.getDevicePrsId())) {
                    beakerSvgInfoVO.setBgs(BeakerBreakerProtectionInfoVO.builder()
                            .breakerPsrId(o.getPsrId())
                            .zoneIDelay(e.getZoneIDelay())
                            .zoneIDelayUnit(CommonUnitEnum.MS.getCode())
                            .zoneIIDelay(e.getZoneIiDelay())
                            .zoneIIDelayUnit(CommonUnitEnum.MS.getCode())
                            .zoneIISetting(e.getZoneIiSetting())
                            .zoneIISettingUnit(CommonUnitEnum.I.getCode())
                            .zoneISetting(e.getZoneISetting())
                            .zoneISettingUnit(CommonUnitEnum.I.getCode())
                            .build());
                }
            });
            beakerStatusInfoVOS.add(beakerSvgInfoVO);
        });
    }

    /**
     * 获取转供前开关数据信息
     *
     * @param dto
     * @return
     */
    public List<BeakerStatusInfoVO> getBeakerStatusInfoZgBefore(BeakerStatusDTO dto) {
        List<BeakerStatusInfoVO> result = new ArrayList<>();
        List<AllSwitchInfoDTO> switchInfoDTOS = null;
        int index = getDataByTimeSlot(dto.getTime());
        DwdShbDsFeederBase dwdShbDsFeederBase = dwdShbDsFeederBaseService.getByPsrId(dto.getLinePsrId());
        if (ObjectUtil.isNull(dwdShbDsFeederBase)) {
            ExceptionCast.cast("线路不存在");
        }
        List<FeederTopo> feederTopos = getFeederTopos(dwdShbDsFeederBase);
        List<AllSwitchInfoListDTO> switchInfoListDTOS = new ArrayList<>();
        StateEstimation stateEstimation = new StateEstimation();
        //获取计划转供前开关信息
        if (dto.getPlanId() != null && !dto.getPlanId().isEmpty()) {
            switchInfoListDTOS = planPowerCutService.getAllSwitchBySchemeId(Long.valueOf(dto.getPlanId()));
            FhzgPlanPowerCut planPowerCut = planPowerCutService.getById(dto.getPlanId());
            if (planPowerCut.getFeederSwitchInfo() != null) {
                stateEstimation = JSON.parseObject(planPowerCut.getFeederSwitchInfo(), StateEstimation.class);
            }
        }
        //获取故障转供前开关信息
        else if (dto.getFaultId() != null && !dto.getFaultId().isEmpty()) {
            switchInfoListDTOS = faultPowerCutService.getAllSwitchBySchemeId(Long.valueOf(dto.getFaultId()));
            FaultPowerCut faultPowerCut = faultPowerCutService.getById(dto.getFaultId());
            if (faultPowerCut.getFeederSwitchInfo() != null) {
                stateEstimation = JSON.parseObject(faultPowerCut.getFeederSwitchInfo(), StateEstimation.class);
            }
        }
        if (switchInfoListDTOS != null && !switchInfoListDTOS.isEmpty()) {
            switchInfoDTOS = switchInfoListDTOS.stream().filter(e -> Objects.equals(e.getFeederId(), dto.getLinePsrId()))
                    .collect(Collectors.toList()).get(0).getAllSwitchList();
        }
        if (switchInfoDTOS != null) {
            List<AllSwitchInfoDTO> finalSwitchInfoDTOS = switchInfoDTOS;
            StateEstimation finalStateEstimation = stateEstimation;
            feederTopos.forEach(to -> {
                String switchType = "0";
                if (to.getPsrType().equals("PD_11100000")) {
                    switchType = "1";
                }
                AllSwitchInfoDTO switchInfoDTO;
                List<AllSwitchInfoDTO> midSwitch;
                List<StateEstimation.StateEstimationSwitchResult> midSwitchZg = null;
                midSwitch = finalSwitchInfoDTOS.stream().filter(e -> Objects.equals(e.getPsrID(), to.getPsrId())).collect(Collectors.toList());
                if (finalStateEstimation != null) {
                    midSwitchZg = finalStateEstimation.getPeriodSwitchSeResult().stream()
                            .filter(e -> Objects.equals(e.getPsrId(), to.getPsrId())).collect(Collectors.toList());
                }
                if (!midSwitch.isEmpty()) {
                    switchInfoDTO = midSwitch.get(0);
                    BeakerStatusInfoVO statusInfoVO = BeakerStatusInfoVO.builder()
                            .breakerPsrId(to.getPsrId())
                            .punit(CommonUnitEnum.P.getCode())
                            .qunit(CommonUnitEnum.Q.getCode())
                            .iunit(CommonUnitEnum.I.getCode())
                            .uunit(CommonUnitEnum.U.getCode())
                            .pvalue(convertToKW(String.valueOf(switchInfoDTO.getP().get(index))))
                            .qvalue(String.valueOf(switchInfoDTO.getQ().get(index)))
                            .uvalue(String.valueOf(switchInfoDTO.getU().get(index)))
                            .ivalue(String.valueOf(switchInfoDTO.getI().get(index)))
                            .sourceSystem("js")
                            .switchType(switchType)
                            .build();
                    if (midSwitchZg != null && !midSwitchZg.isEmpty()) {
                        statusInfoVO.setIsAuto(midSwitchZg.get(0).getIsAuto());
                        statusInfoVO.setStatus(midSwitchZg.get(0).getSeoStatuss().get(0));
                    }
                    result.add(statusInfoVO);
                }
            });
        } else {
            feederTopos.forEach(to -> {
                String switchType = "0";
                if (to.getPsrType().equals("PD_11100000")) {
                    switchType = "1";
                }
                BeakerStatusInfoVO statusInfoVO = BeakerStatusInfoVO.builder().breakerPsrId(to.getPsrId()).switchType(switchType)
                        .sourceSystem("js").build();
                result.add(statusInfoVO);
            });
        }
        return result;
    }

    /**
     * 获取线路上开关状估数据列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<BeakerStatusInfoVO> getBeakerStatusInfoZg(BeakerStatusDTO dto) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<BeakerStatusInfoVO> beakerStatusInfoVOS = new ArrayList<>();
        DwdShbDsFeederBase dwdShbDsFeederBase = dwdShbDsFeederBaseService.getByPsrId(dto.getLinePsrId());
        if (ObjectUtil.isNull(dwdShbDsFeederBase)) {
            ExceptionCast.cast("线路不存在");
        }
        // 所有开关
        List<FeederTopo> feederTopos = getFeederTopos(dwdShbDsFeederBase);
        // 调用状态估算
        List<StateEstimation.StateEstimationSwitchResult> periodSwitchSeResult = new ArrayList<>();
        try {
            StateEstimation s = null;
            //判断是否需要获取计划或故障数据
            if (dto.getPlanId() != null && !"".equals(dto.getPlanId())) {
                FhzgPlanPowerCut planPowerCut = planPowerCutService.getById(dto.getPlanId());
                //判断传入时间是否在计划停电时间内（允许15分钟差值）
                if ((planPowerCut.getPlanStartTime().isBefore(LocalDateTime.parse(dto.getTime(), formatter))
                        && planPowerCut.getPlanEndTime().isAfter(LocalDateTime.parse(dto.getTime(), formatter))
                ) || isTimeDifferenceLessThan15Minutes(LocalDateTime.parse(dto.getTime(), formatter), planPowerCut.getPlanStartTime())) {
                    return getBeakerStatusInfoZgBefore(dto);
                }
            } else if (dto.getFaultId() != null && !"".equals(dto.getFaultId())) {
                FaultPowerCut faultPowerCut = faultPowerCutMapper.selectById(dto.getFaultId());
                //判断传入时间是否满足在故障发生之后（允许15分钟差值）
                if (faultPowerCut.getFaultStartTime().isBefore(LocalDateTime.parse(dto.getTime(), formatter))
                        || isTimeDifferenceLessThan15Minutes(LocalDateTime.parse(dto.getTime(), formatter), faultPowerCut.getFaultStartTime())) {
                    return getBeakerStatusInfoZgBefore(dto);
                    // s = JSON.parseObject(faultPowerCut.getFeederSwitchInfo(), StateEstimation.class);
                }
            } else {
                s = JSON.parseObject(JSON.toJSONString(redisTemplate.opsForValue().get(dto.getLinePsrId() + dto.getTime() + "zg")), StateEstimation.class);
            }
            List<StateEstimation.StateEstimationSwitchResult> ss = new ArrayList<>();
            if (s != null) {
                log.info(JSON.toJSONString(ss));
                ss = s.getPeriodSwitchSeResult();
            } else {
                ss = iStateEstimationApiClient.queryByFeederSave(StateEstimationRequest.builder()
                        .psrIds(Arrays.asList(dto.getLinePsrId()))
                        .containerCode(Arrays.asList(CommonConstant.SWITCH))
                        .startTime(dto.getTime())
                        .endTime(dto.getTime())
                        .isAuto(Boolean.FALSE)
                        .build()).getData().getPeriodSwitchSeResult();
            }
            if (CollectionUtils.isNotEmpty(ss)) {
                periodSwitchSeResult.addAll(ss);
            }
            log.info("状估开关：" + periodSwitchSeResult.size());
            log.info("所有开关：" + feederTopos.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<String> psrIdAuto = new ArrayList<>();
        if (!periodSwitchSeResult.isEmpty()) {
            //获取所有自动化开关psrId
            psrIdAuto = periodSwitchSeResult
                    .stream().filter(a -> "true".equals(a.getIsAuto()))
                    .map(StateEstimation.StateEstimationSwitchResult::getPsrId)
                    .collect(Collectors.toList());
        }
        HashSet<String> psrSet = new HashSet<>(psrIdAuto);
        feederTopos.stream().forEach(o ->
        {
            BeakerSvgInfoVO beakerSvgInfoVO = BeakerSvgInfoVO.builder().breakerPsrId(o.getPsrId()).build();
            if (CollectionUtils.isNotEmpty(periodSwitchSeResult)) {
                periodSwitchSeResult.stream().forEach(e -> {
                    if (o.getPsrId().equals(e.getPsrId())) {
                        String seiIs = "0.0";
                        try {
                            if (StringUtils.isNotEmpty(e.getSeiIs().get(0))) {
                                BigDecimal bigDecimal = new BigDecimal(e.getSeiIs().get(0));
                                seiIs = bigDecimal.multiply(new BigDecimal(1000)).toString();
                            }
                        } catch (Exception exception) {
                            exception.printStackTrace();
                        }
                        String sourceName;
                        //设置来源系统
                        String switchType = "0";
                        if (o.getPsrType().equals("PD_11100000")) {
                            switchType = "1";
                        }
                        if (psrSet.contains(e.getPsrId())) {
                            sourceName = "lc";
                            beakerSvgInfoVO.setLcs(BeakerStatusInfoVO.builder()
                                    .punit(CommonUnitEnum.P.getCode())
                                    .qunit(CommonUnitEnum.Q.getCode())
                                    .iunit(CommonUnitEnum.I.getCode())
                                    .uunit(CommonUnitEnum.U.getCode())
                                    .pvalue(convertToKW(e.getSeiPs().get(0)))
                                    .qvalue(e.getSeiQs().get(0))
                                    .ivalue(seiIs)
                                    .uvalue(e.getSeiUs().get(0))
                                    .status(e.getSeiStatuss().get(0))
                                    .isAuto(e.getIsAuto())
                                    .sourceSystem(sourceName)
                                    .switchType(switchType)
                                    .build());
                        } else {
                            sourceName = "zg";
                            beakerSvgInfoVO.setLcs(BeakerStatusInfoVO.builder()
                                    .punit(CommonUnitEnum.P.getCode())
                                    .qunit(CommonUnitEnum.Q.getCode())
                                    .iunit(CommonUnitEnum.I.getCode())
                                    .uunit(CommonUnitEnum.U.getCode())
                                    .pvalue(convertToKW(e.getSeoPs().get(0)))
                                    .qvalue(e.getSeoQs().get(0))
                                    .ivalue(seiIs)
                                    .uvalue(e.getSeoUs().get(0))
                                    .status(e.getSeoStatuss().get(0))
                                    .isAuto(e.getIsAuto())
                                    .sourceSystem(sourceName)
                                    .switchType(switchType)
                                    .build());
                        }
                    }
                });
            }
            if (beakerSvgInfoVO.getLcs() != null) {
                beakerSvgInfoVO.getLcs().setBreakerPsrId(o.getPsrId());
            } else {
                beakerSvgInfoVO.setLcs(BeakerStatusInfoVO.builder().breakerPsrId(o.getPsrId()).build());
            }
            beakerStatusInfoVOS.add(beakerSvgInfoVO.getLcs());
        });
        return beakerStatusInfoVOS;
    }


    /**
     * 获取线路上开关量测数据列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<BeakerStatusInfoVO> getBeakerStatusInfoLc(BeakerStatusDTO dto) {
        List<BeakerStatusInfoVO> beakerStatusInfoVOS = new ArrayList<>();
        beakerStatusInfoVOS.stream()
                .filter(vo -> "true".equals(vo.getIsAuto()))
                .collect(Collectors.toList());
        DwdShbDsFeederBase dwdShbDsFeederBase = dwdShbDsFeederBaseService.getByPsrId(dto.getLinePsrId());
        if (ObjectUtil.isNull(dwdShbDsFeederBase)) {
            ExceptionCast.cast("线路不存在");
        }
        // 所有开关
        List<FeederTopo> feederTopos = getFeederTopos(dwdShbDsFeederBase);
        List<StateEstimation.StateEstimationSwitchResult> periodSwitchSeResult = new ArrayList<>();
        //调用量测运算
        try {
            List<StateEstimation.StateEstimationSwitchResult> ss = new ArrayList<>();
            StateEstimation s = JSON.parseObject(JSON.toJSONString(redisTemplate.opsForValue().get(dto.getLinePsrId() + dto.getTime() + "zg")), StateEstimation.class);
            if (s != null) {
                log.info(JSON.toJSONString(ss));
                ss = s.getPeriodSwitchSeResult();
            } else {
                ss = siStateEstimationClient.queryPeriodByFeeder(StateEstimationRequest.builder()
                        .psrIds(Arrays.asList(dto.getLinePsrId()))
                        .containerCode(Arrays.asList(CommonConstant.SWITCH))
                        .startTime(dto.getTime())
                        .endTime(dto.getTime())
                        .isAuto(Boolean.FALSE)
                        .build()).getData().getPeriodSwitchSeResult();
            }
            if (CollectionUtils.isNotEmpty(ss)) {
                periodSwitchSeResult.addAll(ss);
            }
            log.info("状估开关：" + periodSwitchSeResult.size());
            log.info("所有开关：" + feederTopos.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
        feederTopos.stream().forEach(o ->
        {
            BeakerSvgInfoVO beakerSvgInfoVO = BeakerSvgInfoVO.builder().breakerPsrId(o.getPsrId()).build();
            if (CollectionUtils.isNotEmpty(periodSwitchSeResult)) {
                periodSwitchSeResult.stream().forEach(e -> {
                    if (o.getPsrId().equals(e.getPsrId())) {
                        String seiIs = "0.0";
                        String seoIs = "0.0";
                        try {
                            if (org.apache.commons.lang3.StringUtils.isNotEmpty(e.getSeiIs().get(0))) {
                                BigDecimal bigDecimal = new BigDecimal(e.getSeiIs().get(0));
                                seiIs = bigDecimal.multiply(new BigDecimal(1000)).toString();
                            }
                            if (StringUtils.isNotEmpty(e.getSeoIs().get(0))) {
                                BigDecimal bigDecimal = new BigDecimal(e.getSeoIs().get(0));
                                seoIs = bigDecimal.multiply(new BigDecimal(1000)).toString();
                            }
                        } catch (Exception exception) {
                            exception.printStackTrace();
                        }
                        beakerSvgInfoVO.setZgs(BeakerStatusInfoVO.builder()
                                .breakerPsrId(o.getPsrId())
                                .punit(CommonUnitEnum.P.getCode())
                                .qunit(CommonUnitEnum.Q.getCode())
                                .iunit(CommonUnitEnum.I.getCode())
                                .uunit(CommonUnitEnum.U.getCode())
                                .pvalue(convertToKW(e.getSeoPs().get(0)))
                                .qvalue(e.getSeoQs().get(0))
                                .ivalue(seoIs)
                                .uvalue(e.getSeoUs().get(0))
                                .status(e.getSeoStatuss().get(0))
                                .build());
                    }
                });
            }
            beakerStatusInfoVOS.add(beakerSvgInfoVO.getZgs());
        });
        return beakerStatusInfoVOS;
    }

    /**
     * 获取线路上开关保供数据列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<BeakerBreakerProtectionInfoVO> getBeakerStatusInfoBg(BeakerStatusDTO dto) {
        List<BeakerBreakerProtectionInfoVO> breakerProtectionInfoVOS = new ArrayList<>();
        DwdShbDsFeederBase dwdShbDsFeederBase = dwdShbDsFeederBaseService.getByPsrId(dto.getLinePsrId());
        if (ObjectUtil.isNull(dwdShbDsFeederBase)) {
            ExceptionCast.cast("线路不存在");
        }
        List<FhzgSwitchProtectionSettings> fhzgSwitchProtectionSettings = new ArrayList<>();
        // 保供
        List<FhzgSwitchProtectionSettings> rdsList = (List<FhzgSwitchProtectionSettings>) redisTemplate.opsForValue()
                .get(dto.getLinePsrId() + "bg");
        if (rdsList != null) {
            fhzgSwitchProtectionSettings = rdsList;
        } else {
            LambdaQueryWrapper<FhzgSwitchProtectionSettings> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FhzgSwitchProtectionSettings::getParentLinePsrId, dwdShbDsFeederBase.getPsrId());
            fhzgSwitchProtectionSettings = fhzgSwitchProtectionSettingsService.list(wrapper);
            redisTemplate.opsForValue()
                    .set(dto.getLinePsrId() + "bg", fhzgSwitchProtectionSettings);
        }
        fhzgSwitchProtectionSettings.forEach(e -> {
            BeakerBreakerProtectionInfoVO breakerProtectionInfoVO = BeakerBreakerProtectionInfoVO.builder()
                    .breakerPsrId(e.getDevicePrsId())
                    .zoneIDelay(e.getZoneIDelay())
                    .zoneIDelayUnit(CommonUnitEnum.MS.getCode())
                    .zoneIIDelay(e.getZoneIiDelay())
                    .zoneIIDelayUnit(CommonUnitEnum.MS.getCode())
                    .zoneIISetting(e.getZoneIiSetting())
                    .zoneIISettingUnit(CommonUnitEnum.I.getCode())
                    .zoneISetting(e.getZoneISetting())
                    .zoneISettingUnit(CommonUnitEnum.I.getCode())
                    .build();
            breakerProtectionInfoVOS.add(breakerProtectionInfoVO);
        });
        return breakerProtectionInfoVOS;
    }

    /**
     * 获取线路上开关转供后数据列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<BeakerStatusInfoVO> getBeakerStatusInfoZgh(BeakerStatusDTO dto) {
        List<AllSwitchInfoDTO> switchInfoDTOS = new ArrayList<>();
        AllSwitchInfoDTO switchInfoDTO = new AllSwitchInfoDTO();
        List<AllSwitchInfoListDTO> switchInfoListDTOS = new ArrayList<>();
        if (dto.getSchemeId() != null && !dto.getSchemeId().isEmpty()) {
            if (dto.getPlanId() != null && !dto.getPlanId().isEmpty()) {
                switchInfoListDTOS = planTransferSchemeService.getAllSwitchBySchemeId(Long.valueOf(dto.getSchemeId()));
            } else if (dto.getFaultId() != null && !dto.getFaultId().isEmpty()) {
                switchInfoListDTOS = faultTransferSchemeService.getAllSwitchBySchemeId(Long.valueOf(dto.getSchemeId()));
            }
        }
        if (switchInfoListDTOS != null) {
            switchInfoDTOS = switchInfoListDTOS.stream().filter(e -> Objects.equals(e.getFeederId(), dto.getLinePsrId()))
                    .collect(Collectors.toList()).get(0).getAllSwitchList();
            switchInfoDTO = switchInfoDTOS.stream()
                    .filter(e -> Objects.equals(e.getPsrID(), dto.getPsrId())).collect(Collectors.toList()).get(0);
            int index = getDataByTimeSlot(dto.getTime());
            BigDecimal p = switchInfoDTO.getP().get(index);
            BigDecimal q = switchInfoDTO.getQ().get(index);
            BigDecimal u = switchInfoDTO.getU().get(index);
            BigDecimal i = switchInfoDTO.getI().get(index);
            BeakerStatusInfoVO beakerStatusInfoVO = BeakerStatusInfoVO.builder()
                    .breakerPsrId(dto.getPsrId())
                    .punit(CommonUnitEnum.P.getCode())
                    .qunit(CommonUnitEnum.Q.getCode())
                    .iunit(CommonUnitEnum.I.getCode())
                    .uunit(CommonUnitEnum.U.getCode())
                    .pvalue(convertToKW(String.valueOf(p)))
                    .qvalue(String.valueOf(q))
                    .uvalue(String.valueOf(u))
                    .ivalue(String.valueOf(i))
                    .build();
            List<BeakerStatusInfoVO> result = new ArrayList<>();
            result.add(beakerStatusInfoVO);
            return result;
        }

        List<BeakerStatusInfoVO> beakerStatusInfoVOS = new ArrayList<>();
        DwdShbDsFeederBase dwdShbDsFeederBase = dwdShbDsFeederBaseService.getByPsrId(dto.getLinePsrId());
        // 所有开关
        List<FeederTopo> feederTopos = getFeederTopos(dwdShbDsFeederBase);
        List<BeakerStatusInfoVO> rdsList = (List<BeakerStatusInfoVO>) redisTemplate.opsForValue().get(dto.getSchemeId());
        if (rdsList != null) {
            return rdsList;
        } else {
            if (StringUtils.isNotEmpty(dto.getPlanId()) || StringUtils.isNotEmpty(dto.getSchemeId())) {
                // 转供后的逻辑
                String schemeId = dto.getSchemeId();
                FhzgPlanTransferScheme fhzgPlanTransferScheme = new FhzgPlanTransferScheme();
                List<FhzgPlanTransferSchemeDTO> fhzgPlanTransferSchemeByPlanId = new ArrayList<>();
                if (StringUtils.isEmpty(dto.getSchemeId())) {
                    fhzgPlanTransferScheme.setPlanId(Long.valueOf(dto.getPlanId()));
                    fhzgPlanTransferScheme.setSchemeState("01");
                    fhzgPlanTransferSchemeByPlanId = fhzgPlanTransferSchemeMapper.getFhzgPlanTransferSchemeByPlanId(fhzgPlanTransferScheme);
                    if (!fhzgPlanTransferSchemeByPlanId.isEmpty()) {
                        schemeId = String.valueOf(fhzgPlanTransferSchemeByPlanId.get(0).getId());
                    } else {
                        fhzgPlanTransferSchemeByPlanId = fhzgPlanTransferSchemeMapper.getFhzgFaultTransferSchemeByFaultId(fhzgPlanTransferScheme);
                        schemeId = String.valueOf(fhzgPlanTransferSchemeByPlanId.get(0).getId());
                    }
                }
                if (StringUtils.isNotEmpty(schemeId)) {
                    LambdaQueryWrapper<FhzgInfoBreakerSvgAfter> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(FhzgInfoBreakerSvgAfter::getSchemeId, Long.valueOf(schemeId));
                    List<FhzgInfoBreakerSvgAfter> fhzgInfoBreakerSvgAfters = fhzgInfoBreakerSvgAfterMapper.selectList(wrapper);
                    fhzgInfoBreakerSvgAfters.stream().forEach(o ->
                    {
                        for (FeederTopo feederTopo : feederTopos) {
                            if (feederTopo.getPsrId().equals(o.getStartSwitchId())) {
                                BeakerStatusInfoVO beakerStatusInfoVO =
                                        BeakerStatusInfoVO.builder()
                                                .breakerPsrId(o.getStartSwitchId())
                                                .punit(CommonUnitEnum.P.getCode())
                                                .qunit(CommonUnitEnum.Q.getCode())
                                                .iunit(CommonUnitEnum.I.getCode())
                                                .uunit(CommonUnitEnum.U.getCode())
                                                .pvalue(Optional.ofNullable(convertToKW(o.getAfterP())).map(String::valueOf).orElse(null))
                                                .qvalue(Optional.ofNullable(o.getAfterQ()).map(String::valueOf).orElse(null))
                                                .ivalue(Optional.ofNullable(o.getAfterI()).map(String::valueOf).orElse(null))
                                                .build();
                                beakerStatusInfoVOS.add(beakerStatusInfoVO);

                            }
                        }
                    });
                }
            }
            redisTemplate.opsForValue().set(dto.getSchemeId(), beakerStatusInfoVOS);
            return beakerStatusInfoVOS;
        }
    }

    /**
     * 根据开关ID获取对应状估，量测，转供后数据
     *
     * @param dto
     * @return
     */
    @Override
    public BeakerSvgInfoVO getBeakerSvgInfoVOByPsrId(BeakerStatusDTO dto) {
        List<StateEstimation.StateEstimationSwitchResult> periodSwitchSeResult = new ArrayList<>();
        DwdShbDsFeederBase dwdShbDsFeederBase = dwdShbDsFeederBaseService.getByPsrId(dto.getLinePsrId());
        if (ObjectUtil.isNull(dwdShbDsFeederBase)) {
            ExceptionCast.cast("线路不存在");
        }
        // 调用状态估算
        StateEstimation s = null;
        //判断是否需要获取计划或故障数据
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        s = JSON.parseObject(JSON.toJSONString(redisTemplate.opsForValue().get(dto.getLinePsrId() + dto.getTime() + "zg")), StateEstimation.class);
        if (s != null) {
            periodSwitchSeResult = s.getPeriodSwitchSeResult();
        } else {
            try {
                periodSwitchSeResult = iStateEstimationApiClient.queryByFeederSave(StateEstimationRequest.builder()
                        .psrIds(Collections.singletonList(dto.getLinePsrId()))
                        .containerCode(Collections.singletonList(CommonConstant.SWITCH))
                        .startTime(dto.getTime())
                        .endTime(dto.getTime())
                        .isAuto(Boolean.FALSE)
                        .build()).getData().getPeriodSwitchSeResult();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        BeakerSvgInfoVO beakerSvgInfoVO = BeakerSvgInfoVO.builder().breakerPsrId(dto.getPsrId()).build();
        if (CollectionUtils.isNotEmpty(periodSwitchSeResult)) {
            periodSwitchSeResult.forEach(e -> {
                if (dto.getPsrId().equals(e.getPsrId())) {
                    String seiIs = "0.0";
                    String seoIs = "0.0";
                    try {
                        if (StringUtils.isNotEmpty(e.getSeiIs().get(0))) {
                            BigDecimal bigDecimal = new BigDecimal(e.getSeiIs().get(0));
                            seiIs = bigDecimal.multiply(new BigDecimal(1000)).toString();
                        }
                        if (StringUtils.isNotEmpty(e.getSeoIs().get(0))) {
                            BigDecimal bigDecimal = new BigDecimal(e.getSeoIs().get(0));
                            seoIs = bigDecimal.multiply(new BigDecimal(1000)).toString();
                        }
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }
                    if (Objects.equals(e.getIsAuto(), "true")) {
                        beakerSvgInfoVO.setLcs(BeakerStatusInfoVO.builder()
                                .breakerPsrId(dto.getPsrId())
                                .punit(CommonUnitEnum.P.getCode())
                                .qunit(CommonUnitEnum.Q.getCode())
                                .iunit(CommonUnitEnum.I.getCode())
                                .uunit(CommonUnitEnum.U.getCode())
                                .pvalue(convertToKW(e.getSeiPs().get(0)))
                                .qvalue(e.getSeiQs().get(0))
                                .ivalue(seiIs)
                                .uvalue(e.getSeiUs().get(0))
                                .status(e.getSeiStatuss().get(0))
                                .build());
                    }
                    beakerSvgInfoVO.setZgs(BeakerStatusInfoVO.builder()
                            .breakerPsrId(dto.getPsrId())
                            .punit(CommonUnitEnum.P.getCode())
                            .qunit(CommonUnitEnum.Q.getCode())
                            .iunit(CommonUnitEnum.I.getCode())
                            .uunit(CommonUnitEnum.U.getCode())
                            .pvalue(convertToKW(e.getSeoPs().get(0)))
                            .qvalue(e.getSeoQs().get(0))
                            .ivalue(seoIs)
                            .uvalue(e.getSeoUs().get(0))
                            .status(e.getSeoStatuss().get(0))
                            .build());
                }
            });
        }
        LambdaQueryWrapper<FhzgSwitchProtectionSettings> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FhzgSwitchProtectionSettings::getDevicePrsId, dto.getPsrId());
        List<FhzgSwitchProtectionSettings> fhzgSwitchProtectionSettings = fhzgSwitchProtectionSettingsService.list(wrapper);
        if (fhzgSwitchProtectionSettings != null) {
            fhzgSwitchProtectionSettings.forEach(e -> {
                BeakerBreakerProtectionInfoVO breakerProtectionInfoVO = BeakerBreakerProtectionInfoVO.builder()
                        .breakerPsrId(e.getDevicePrsId())
                        .zoneIDelay(e.getZoneIDelay())
                        .zoneIDelayUnit(CommonUnitEnum.MS.getCode())
                        .zoneIIDelay(e.getZoneIiDelay())
                        .zoneIIDelayUnit(CommonUnitEnum.MS.getCode())
                        .zoneIISetting(e.getZoneIiSetting())
                        .zoneIISettingUnit(CommonUnitEnum.I.getCode())
                        .zoneISetting(e.getZoneISetting())
                        .zoneISettingUnit(CommonUnitEnum.I.getCode())
                        .oc1_delay(e.getOc1Delay())
                        .oc1_value(e.getOc1Value())
                        .oc2_delay(e.getOc2Delay())
                        .oc2_value(e.getOc2Value())
                        .oc3_delay(e.getOc3Delay())
                        .oc3_value(e.getOc3Value())
                        .recloseEnableStatus(String.valueOf(e.getRecloseEnableStatus()))
                        .build();
                beakerSvgInfoVO.setBgs(breakerProtectionInfoVO);
            });
        }
        if (dto.getSchemeId() != null && !dto.getSchemeId().isEmpty()) {
            try {
                List<BeakerStatusInfoVO> beakerStatusInfoVOS = getBeakerStatusInfoZgh(dto);
                beakerStatusInfoVOS.forEach(b -> {
                    if (Objects.equals(b.getBreakerPsrId(), dto.getPsrId())) {
                        beakerSvgInfoVO.setZghs(b);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return beakerSvgInfoVO;
    }

    /**
     * 批量保存状估数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<BeakerStatusInfoVO> saveStatusInfoZgList(BeakerStatusDTO dto) {
        dto.getCity().forEach(e -> {
            LambdaQueryWrapper<DwdShbDsFeederBase> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DwdShbDsFeederBase::getMaintOrg, e);
            List<DwdShbDsFeederBase> feederList = dwdshbDsFeederBaseMapper.selectList(wrapper);
            feederList.forEach(f -> {
                dto.setPsrId(f.getPsrId());
                dto.setPlanId(null);
                dto.setFaultId(null);
                dto.setSchemeId(null);
                CompletableFuture.runAsync(() -> getBeakerStatusInfoZg(dto), multiThreadExecuteService.getExecutor());
            });
        });
        return null;
    }

    /**
     * 查询所有目标区县下线路并删除缓存pqui数据
     *
     * @param dto
     */
    public void deleteSvgPqui(BeakerStatusDTO dto) {
        dto.getCity().forEach(e -> {
            LambdaQueryWrapper<DwdShbDsFeederBase> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DwdShbDsFeederBase::getMaintOrg, dto.getCity());
            List<DwdShbDsFeederBase> feederList = dwdshbDsFeederBaseMapper.selectList(wrapper);
            feederList.forEach(f -> {
                deleteFromRedis(f.getPsrId() + "*" + "zg");
            });
        });
    }

    /**
     * 查询开关配变列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<SwitchOrTransformerVO> getSwitchAndTransformerList(SwitchOrTransformerDTO dto) {
        List<String> psrType = new ArrayList<>(Arrays.asList(DictConstants.PB_PSR_TYPE.split(",")));
        List<String> psrTypeKg = Arrays.asList(DictConstants.KG_PSR_TYPE.split(","));
        psrType.addAll(psrTypeKg);
        List<SwitchOrTransformerVO> result = dwdShbDsSwitchBaseMapper.getSwitchAndTransformerList(dto.getName(), dto.getFeederId(), psrType);
        result.forEach(e -> {
            if (psrTypeKg.contains(e.getPsrType())) {
                e.setType(1);
            } else {
                e.setType(2);
            }
        });
        return result;
    }

    /**
     * 查询指定开关或配变用于定位的id
     *
     * @param dto
     * @return
     */
    @Override
    public SwitchOrTransformerVO getSwitchOrTransformerInfo(SwitchOrTransformerDTO dto) {
        List<String> psrTypePb = Arrays.asList(DictConstants.PB_PSR_TYPE.split(","));
        List<String> psrTypeKg = Arrays.asList(DictConstants.KG_PSR_TYPE.split(","));
        LambdaQueryWrapper<FeederTopo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FeederTopo::getPsrId, dto.getPsrId());
        List<FeederTopo> list = feederTopoMapper.selectList(lambdaQueryWrapper);
        if (!list.isEmpty()) {
            //判断入参是开关或配变
            String psrType = list.get(0).getPsrType();
            SwitchOrTransformerVO switchOrTransformerVO = dwdShbDsSwitchBaseMapper.getShowSwitch(dto.getFeederId(), dto.getPsrId());
            if (psrTypePb.contains(psrType)) {
                switchOrTransformerVO.setType(2);
                switchOrTransformerVO.setStartSwitchId(switchOrTransformerVO.getStartSwitchId() + "_fhd");
                String pid = getFirstSwitchOfPb(dto);
                switchOrTransformerVO.setPsrId(pid + "_fhd");
                return switchOrTransformerVO;
            } else if (psrTypeKg.contains(psrType)) {
                switchOrTransformerVO.setType(1);
                //判断开关是否隐藏
                if (!switchOrTransformerVO.getStartSwitchId().equals(switchOrTransformerVO.getPsrId())) {
                    switchOrTransformerVO.setStartSwitchId(switchOrTransformerVO.getStartSwitchId() + "_fhd");
                }
                return switchOrTransformerVO;
            }
        }
        return null;
    }

    //查找上级开关id
    public String getFirstSwitchOfPb(SwitchOrTransformerDTO dto) {
        List<String> psrTypeKg = Arrays.asList(DictConstants.KG_PSR_TYPE.split(","));
        List<TopoDTO> fullTopoList = dwdShbDsSwitchBaseMapper.getTree(dto.getFeederId());
        Map<String, TopoDTO> topoMap = fullTopoList.stream()
                .collect(Collectors.toMap(TopoDTO::getPsrId, Function.identity()));
        String currentId = dto.getPsrId();
        while (currentId != null) {
            TopoDTO topoDTO = topoMap.get(currentId);
            if (topoDTO == null) {
                break;
            }
            if (topoDTO.getPsrType() != null && psrTypeKg.contains(topoDTO.getPsrType())) {
                return topoDTO.getPsrId();
            }
            currentId = topoDTO.getPid();
        }
        return null;
    }

    /**
     * 从redis中删除指定线路id对应所有pqui数据
     *
     * @param pattern
     */
    public void deleteFromRedis(String pattern) {
        Set<String> keys = new HashSet<>();
        Cursor<byte[]> cursor = redisTemplate.execute(
                (RedisCallback<Cursor<byte[]>>) connection ->
                        connection.scan(ScanOptions.scanOptions().match(pattern).count(1000).build())
        );
        while (cursor.hasNext()) {
            keys.add(new String(cursor.next()));
        }
        redisTemplate.delete(keys);
        try {
            cursor.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List<FeederTopo> getFeederTopos(DwdShbDsFeederBase dwdShbDsFeederBase) {
        LambdaQueryWrapper<FeederTopo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FeederTopo::getFeeder, dwdShbDsFeederBase.getPsrId());
        final String[] split = DictConstants.KG_PSR_TYPE.split(",");
        wrapper.in(FeederTopo::getPsrType, Arrays.asList(split));
        //动态切换表名
//*ztj         ArgTableNameHandler.setArgument(fhzgOrganSuffixMapper.getOrganSuffixByPsrIdOrFeeder(null, dwdShbDsFeederBase.getPsrId()));
        List<FeederTopo> feederTopos = feederTopoMapper.selectList(wrapper);
        return feederTopos;
    }

    @Override
    public PqiuCurveInfoVO getPqiuCurveInfo(StateEstimationEquipRequest dto) {
        ApiResponse<StateEstimation> stateEstimationApiResponse = siStateEstimationClient.queryPeriodByEquip(dto);
        StateEstimation data = stateEstimationApiResponse.getData();
        List<List<Object>> seis = new ArrayList<>();
        List<List<Object>> seps = new ArrayList<>();
        List<List<Object>> seqs = new ArrayList<>();
        List<List<Object>> seus = new ArrayList<>();
        for (int i = 0; i < data.getPointTime().size(); i++) {
            BigDecimal sei = new BigDecimal(0);
            BigDecimal seu = new BigDecimal(0);
            BigDecimal sep = new BigDecimal(0);
            BigDecimal seq = new BigDecimal(0);
            try {
                if (CollectionUtils.isNotEmpty(data.getPeriodSwitchSeResult().get(i).getSeiIs())
                        && StringUtils.isNotEmpty(data.getPeriodSwitchSeResult().get(i).getSeiIs().get(0))) {
                    BigDecimal bigDecimal = new BigDecimal(data.getPeriodSwitchSeResult().get(i).getSeiIs().get(0));
                    sei = bigDecimal.multiply(new BigDecimal(1000));
                }
                if (CollectionUtils.isNotEmpty(data.getPeriodSwitchSeResult().get(i).getSeiUs())
                        && StringUtils.isNotEmpty(data.getPeriodSwitchSeResult().get(i).getSeiUs().get(0))) {
                    seu = new BigDecimal(data.getPeriodSwitchSeResult().get(i).getSeiUs().get(0));
                }
                if (CollectionUtils.isNotEmpty(data.getPeriodSwitchSeResult().get(i).getSeiPs())
                        && StringUtils.isNotEmpty(data.getPeriodSwitchSeResult().get(i).getSeiPs().get(0))) {
                    sep = new BigDecimal(data.getPeriodSwitchSeResult().get(i).getSeiPs().get(0));
                }
                if (CollectionUtils.isNotEmpty(data.getPeriodSwitchSeResult().get(i).getSeiQs())
                        && StringUtils.isNotEmpty(data.getPeriodSwitchSeResult().get(i).getSeiQs().get(0))) {
                    seq = new BigDecimal(data.getPeriodSwitchSeResult().get(i).getSeiQs().get(0));
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            seis.add(Arrays.asList(data.getPointTime().get(i), sei));
            seus.add(Arrays.asList(data.getPointTime().get(i), seu));
            seps.add(Arrays.asList(data.getPointTime().get(i), sep));
            seqs.add(Arrays.asList(data.getPointTime().get(i), seq));
        }
        return PqiuCurveInfoVO.builder().seps(seps).seus(seus).seqs(seqs).seis(seis).build();
    }

    /**
     * 获取入参时刻与起点时刻的差值（15分钟为1刻）
     *
     * @param time
     * @return
     */
    public int getDataByTimeSlot(String time) {
        LocalDateTime inputTime = LocalDateTime.parse(time,
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 计算当天零点到输入时间的分钟差
        LocalDate currentDate = inputTime.toLocalDate();
        LocalDateTime midnight = currentDate.atStartOfDay();
        long totalMinutes = Duration.between(midnight, inputTime).toMinutes();

        // 计算下标（每15分钟一个时段）
        return (int) (totalMinutes / 15);
    }

    /**
     * 获取当日起点时间
     *
     * @param dateTime
     * @return
     * @throws ParseException
     */
    private String getStartOfDay(String dateTime) throws ParseException {
        Date date = sdf.get().parse(dateTime);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return sdf.get().format(calendar.getTime());
    }

    private String convertTimeFormat(String original) {
        DateTimeFormatter dateTimeFormat = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime dateTime = LocalDateTime.parse(original, dateTimeFormat);
        return dateTime.format(dateTimeFormatter);
    }

    private boolean isTimeDifferenceLessThan15Minutes(LocalDateTime time1, LocalDateTime time2) {
        try {
            Duration duration = Duration.between(time1, time2).abs();
            return duration.toMinutes() < 15;
        } catch (Exception e) {
            throw new IllegalArgumentException("时间格式不正确，请使用'yyyy-MM-dd HH:mm:ss'格式", e);
        }
    }

    private String convertToKW(String p) {
        if (StringUtils.isEmpty(p)) {
            return null;
        }
        String result;
        try {
            result = new BigDecimal(p).multiply(new BigDecimal("1000")).stripTrailingZeros().toString();
        } catch (Exception e) {
            return null;
        }
        return result;
    }

    private String convertToKW(BigDecimal p) {
        if (p == null) {
            return null;
        }
        String result;
        try {
            result = p.multiply(new BigDecimal("1000")).stripTrailingZeros().toString();
        } catch (Exception e) {
            return null;
        }
        return result;
    }
}
