package com.hdkj.lt.mq.service.wholeStation.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.lang.generator.SnowflakeGenerator;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdkj.lt.core.bizms.modle.dto.wholeStation.*;
import com.hdkj.lt.core.bizms.modle.po.FeederTopo;
import com.hdkj.lt.core.bizms.modle.po.wholeStation.FhzgWholeStationPowerCutTemp;
import com.hdkj.lt.modle.dto.wholeStation.Feeder;
import com.hdkj.lt.modle.dto.wholeStation.Scheme;
import com.hdkj.lt.modle.dto.wholeStation.VolDetail;
import com.hdkj.lt.mq.mapper.base.FeederTopoMapper;
import com.hdkj.lt.mq.mapper.wholeStation.FhzgWholeStationPowerCutTempMapper;
import com.hdkj.lt.mq.service.wholeStation.FhzgWholeStationPowerCutTempService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @author userlrk
 * @description 针对表【fhzg_whole_station_power_cut_temp】的数据库操作Service实现
 * @createDate 2025-08-15 10:43:36
 */
@Service
public class FhzgWholeStationPowerCutTempServiceImpl extends ServiceImpl<FhzgWholeStationPowerCutTempMapper, FhzgWholeStationPowerCutTemp>
        implements FhzgWholeStationPowerCutTempService {
    @Autowired
    private FeederTopoMapper feederTopoMapper;

    /**
     * 解析整站停电方案数据（转json格式）
     *
     * @param schemeList
     * @return
     */
    public Boolean dealWithWholeStationScheme(List<Scheme> schemeList) {
        Snowflake snowflake = IdUtil.getSnowflake(1,1);
        //目标格式
        WholeStationPowerCutSchemeVO powerCutSchemeDTO = new WholeStationPowerCutSchemeVO();
        List<TransferSchemeVO> transferSchemeList = new ArrayList<>();
        //方案计数
        int[] count = {0};
        schemeList.forEach(e -> {
            TransferSchemeVO transferSchemeVO = new TransferSchemeVO();
            transferSchemeVO.setSchemeId(String.valueOf(snowflake.nextId()));
            transferSchemeVO.setSchemeName(e.getDetalDesc());
            //处理开关动作顺序
            dealWithSwitchSeq(e, transferSchemeVO);
            //处理带供 转供线路详情
            dealWithTransferPath(e, transferSchemeVO);
            //处理电压越限幅度
            dealWithLowerVoltage(e, transferSchemeVO);
            //处理线路线损
            dealWithLineLoss(e, transferSchemeVO);
            //处理转供路径渲染范围
            dealWithTransferAreal(e, transferSchemeVO);
            //判断是否推荐方案
            if (Boolean.TRUE.equals(e.getFinalCheck().getIs_safe())) {
                transferSchemeVO.setSchemeCheck("0");
                count[0]++;
            }
            transferSchemeVO.setEvaluationScore("90");
            //TODO 损失用户列表
            //TODO 保电用户列表
            transferSchemeList.add(transferSchemeVO);

        });
        powerCutSchemeDTO.setSchemeList(transferSchemeList);
        FhzgWholeStationPowerCutTemp fhzgWholeStationPowerCutTemp = new FhzgWholeStationPowerCutTemp();
        fhzgWholeStationPowerCutTemp.setId(snowflake.nextId());
        powerCutSchemeDTO.setCheckSuccessCount(count[0]);
        powerCutSchemeDTO.setCheckFailCount(schemeList.size() - count[0]);
        fhzgWholeStationPowerCutTemp.setTransferScheme(JSON.toJSONString(powerCutSchemeDTO));
        this.save(fhzgWholeStationPowerCutTemp);
        return true;
    }

    /**
     * 处理开关动作顺序相关参数
     *
     * @param scheme
     */
    public void dealWithSwitchSeq(Scheme scheme, TransferSchemeVO transferSchemeVO) {
        //开关动作顺序详情
        List<TransferSwitchingSequenceVO> transferSequenceDTOS = new ArrayList<>();
        Snowflake snowflake = IdUtil.getSnowflake(1,1);
        //动作顺序计数
        int[] count = {0};
        //非自动化开关数量计数
        int[] countSwitch = {0};
        //获取方案中开关动作顺序内容
        scheme.getSwitchOp().getListSwitchOp().forEach(e -> {
            //开关动作id
            Long SwitchingId = snowflake.nextId();
            TransferSwitchingSequenceVO sequenceDTO = new TransferSwitchingSequenceVO();
            //设置开关操作
            if (e.getOperation_type().equals("close")) {
                sequenceDTO.setOperationContent("1");
            } else if (e.getOperation_type().equals("open")) {
                sequenceDTO.setOperationContent("0");
            }
            //设置是否三遥
            if (e.getAutoType().equals("auto3Y")) {
                sequenceDTO.setIsAutoSwitch("1");
            } else {
                sequenceDTO.setIsAutoSwitch("0");
                countSwitch[0]++;
            }
            //设置其他值（合环终态默认通过，具体信息暂无）
            sequenceDTO.setSwitchingId(SwitchingId).setSwitchId(e.getBreaker_id())
                    .setSwitchName(e.getName()).setSwitchingSeq(count[0]++)
                    .setFinalStateCheck("1").setLoopCloseCheck("1");
            transferSequenceDTOS.add(sequenceDTO);
        });
        //自动化-非自动化开关数量
        transferSchemeVO.setNonAutoSwitchOperationTimes(countSwitch[0]);
        transferSchemeVO.setSwitchOperationTimes(transferSequenceDTOS.size());
        //填入返回
        transferSchemeVO.setTransferSwitchingSequenceVOList(transferSequenceDTOS);
    }

    /**
     * 处理转供路径-带供线路明细
     *
     * @param scheme
     * @param transferSchemeVO
     */
    public void dealWithTransferPath(Scheme scheme, TransferSchemeVO transferSchemeVO) {
        //转供线路
        List<TransferPathVO> transferPathVOList = new ArrayList<>();
        //带供线路
        List<OppositePathVO> oppositePathVOList = new ArrayList<>();
        //线路细明
        List<Feeder> listFeeder = scheme.getFeederResult().getListFeeder();
        //线路id与线路详情映射map
        Map<String, Feeder> feederMap = listFeeder.stream()
                .collect(Collectors.toMap(Feeder::getPsrID, a -> a,
                        (existing, replacement) -> existing));
        //线路负荷详情
        Map<String, Double> feederloadMap = new HashMap<>();
        //处理线路详情
        scheme.getFeederXferResult().getListFeederXfer().forEach(e -> {
            //带供线路额定电流
            Double rateCurrent = feederMap.get(e.getFeederIn_id()).getRateCurrent();
            //带供线路带供后电流
            Double afterI = feederMap.get(e.getFeederIn_id()).getAfterI();
            OppositePathVO oppositePathVO = new OppositePathVO();
            //带供线路详情
            oppositePathVO.setLineId(e.getFeederIn_id()).setLineName(e.getFeederIn_name())
                    .setCarriedLoad(String.format("%.2f", e.getXfer_p() * 1000))
                    .setRateCurrent(String.format("%.2f", rateCurrent))
                    .setAfterI(String.valueOf(afterI))
                    .setAfterTransferLoadRate(String.format("%.2f", (afterI / rateCurrent) * 100));
            oppositePathVOList.add(oppositePathVO);
            //转供线路
            TransferPathVO transferPathVO = new TransferPathVO();
            //转供线路详情
            transferPathVO.setLineId(e.getFeederOut_id())
                    .setLineName(e.getFeederOut_name())
                    .setCarriedLoad(String.format("%.2f", e.getXfer_p() * 1000))
                    .setTransferLoad(String.valueOf(e.getXfer_p() * 1000))
                    .setOppositeLineId(e.getFeederIn_id())
                    .setOppositeLineName(e.getFeederIn_name());
            //设置线路与线路负载映射
            if (feederloadMap.containsKey(e.getFeederOut_id())) {
                double newP = feederloadMap.get(e.getFeederOut_id()) + e.getXfer_p();
                feederloadMap.put(e.getFeederOut_id(), newP);
            } else {
                feederloadMap.put(e.getFeederOut_id(), e.getXfer_p());
            }
            transferPathVOList.add(transferPathVO);
        });
        transferPathVOList.forEach(p -> {
            //线路总负负荷
            double feederP = feederloadMap.get(p.getLineId());
            //当前线路带供负荷
            double transferP = Double.parseDouble(p.getTransferLoad());
            //设置转出负荷比例
            p.setTransferLoadRatio(String.format("%.2f", transferP / (feederP * 10)));
            p.setTransferLoad(String.format("%.2f", transferP));
        });
        //合并重复带供线路，带供负荷取合，其他不变
        Collection<OppositePathVO> merged = oppositePathVOList.stream().collect(Collectors.toMap(
                OppositePathVO::getLineId, Function.identity(),
                (a1, a2) -> {
                    OppositePathVO pathVO =
                            new OppositePathVO(a1.getLineId(), a1.getLineName(),
                                    String.valueOf(Double.parseDouble(a1.getCarriedLoad()) + Double.parseDouble(a2.getCarriedLoad())
                                    ),
                                    a1.getRateCurrent(), a1.getAfterI(), a1.getAfterTransferLoadRate()
                                    , null);
                    return pathVO;
                }
        )).values();
        List<OppositePathVO> oppositePathVOListResult = new ArrayList<>(merged);
        //设置返回
        transferSchemeVO.setTransferPathVOList(transferPathVOList);
        transferSchemeVO.setOppositePathVOList(oppositePathVOListResult);
    }

    /**
     * 处理电压越限数据
     *
     * @param scheme
     * @param transferSchemeVO
     */
    public void dealWithLowerVoltage(Scheme scheme, TransferSchemeVO transferSchemeVO) {
        //配变低电压列表
        List<TransferDistributionVoltageVO> voltageDTOS = new ArrayList<>();
        //转供后电压越上限列表
        List<String> overList = scheme.getVolResult().getSummary().getAfter().getOverMaxList();
        //转供后电压越下限列表
        List<String> underList = scheme.getVolResult().getSummary().getAfter().getUnderMinList();
        //越限设备台账
        List<VolDetail> details = scheme.getVolResult().getDetails();
        //处理设备信息
        details.forEach(e -> {
            TransferDistributionVoltageVO voltageDTO = new TransferDistributionVoltageVO();

            double volOverLimit = 0;
            //电压越上限下限分别计算越限幅度
            if (overList.contains(e.getPsrID())) {
                voltageDTO.setVolType("2");
                volOverLimit = ((e.getAfter_U() - 10.7) / 10) * 100;
            } else if (underList.contains(e.getPsrID())) {
                voltageDTO.setVolType("1");
                volOverLimit = ((9.3 - e.getAfter_U()) / 10) * 100;
            } else {
                voltageDTO.setVolType("3");
            }
            //配置用户类型
            if (e.getLoadType().equals("MV_CUSTOMER")) {
                voltageDTO.setUserType("中压用户接入点");
            } else {
                voltageDTO.setUserType("公变");
            }
            voltageDTO.setUserName(e.getName()).setUserId(e.getPsrID())
                    .setVolOverLimit(String.format("%.2f", volOverLimit))
                    .setAfterTransferVol(String.valueOf(e.getAfter_U()));
            if (voltageDTO.getVolType().equals("2") || voltageDTO.getVolType().equals("1")) {
                voltageDTOS.add(voltageDTO);
            }
        });
        transferSchemeVO.setTransferDistributionVoltageVOList(voltageDTOS);
    }

    /**
     * 处理线路线损
     *
     * @param scheme
     * @param transferSchemeVO
     */
    public void dealWithLineLoss(Scheme scheme, TransferSchemeVO transferSchemeVO) {
        //线损详情
        TransferLineLossVO lineLossDTO = new TransferLineLossVO();
        //转供前线损统计
        double lineLossBefore = 0;
        //转供后线损统计
        double lineLossAfter = 0;
        //线损用户列表
        List<TransferLineLossDetailVO> transferLineLossDetailVOList = new ArrayList<>();
        scheme.getFeederResult().getListFeeder().forEach(e -> {
            TransferLineLossDetailVO detailDTO = new TransferLineLossDetailVO();
            detailDTO.setLineId(e.getPsrID()).setLineName(e.getName())
                    .setBeforeTransferLineLoss(String.format("%2f", e.getLineLossBefore() * 1000))
                    .setAfterTransferLineLoss(String.format("%2f", e.getLineLossAfter() * 1000));
            transferLineLossDetailVOList.add(detailDTO);
        });
        for (TransferLineLossDetailVO detailDTO : transferLineLossDetailVOList
        ) {
            lineLossBefore = lineLossBefore + Double.parseDouble(detailDTO.getBeforeTransferLineLoss());
            lineLossAfter = lineLossAfter + Double.parseDouble(detailDTO.getAfterTransferLineLoss());
        }
        lineLossDTO.setBeforeTransferLineLossCount(String.valueOf(lineLossBefore));
        lineLossDTO.setAfterTransferLineLossCount(String.valueOf(lineLossAfter));
        lineLossDTO.setTransferLineLossDetailVOList(transferLineLossDetailVOList);
        transferSchemeVO.setTransferLineLossVO(lineLossDTO);
    }

    //转供路径获取
    public void dealWithTransferAreal(Scheme scheme, TransferSchemeVO transferSchemeVO) {
        List<BreakerAreaVO> breakerAreaVOList = new ArrayList<>();
        //构建被带供线路与带供线路数组见的映射
        Map<String, List<String>> feederInToOutMap = new HashMap<>();
        if (scheme.getFeederXferResult().getListFeederXfer().isEmpty()) {
            return;
        }
        scheme.getFeederXferResult().getListFeederXfer().forEach(e -> {
            if (feederInToOutMap.containsKey(e.getFeederOut_id())) {
                List<String> list = feederInToOutMap.get(e.getFeederOut_id());
                list.add(e.getFeederIn_id());
                feederInToOutMap.put(e.getFeederOut_id(), list);
            } else {
                feederInToOutMap.put(e.getFeederOut_id(), Collections.singletonList(e.getFeederIn_id()));
            }
        });
        feederInToOutMap.forEach((a, b) -> {
            //带供线路数量小于1时所有本侧设备由该线路带供
            if (b.size() <= 1) {
                BreakerAreaVO breakerAreaVO = new BreakerAreaVO();
                List<String> list = getTransferAreal(a);
                breakerAreaVO.setMidSwitch(list);
                if (b.size() == 1) {
                    breakerAreaVO.setOppositeLineId(b.get(0));
                }
                breakerAreaVOList.add(breakerAreaVO);
            } else {
                //带供线路数量大于2时需要计算每条线路分别带供哪些开关
                b.forEach(feeder -> {
                    BreakerAreaVO breakerAreaVO = new BreakerAreaVO();
                    breakerAreaVO.setOppositeLineId(feeder);
                    breakerAreaVOList.add(breakerAreaVO);
                });
            }
        });
        transferSchemeVO.setBreakerAreaVOList(breakerAreaVOList);
    }

    //获取线路中所有设备
    public List<String> getTransferAreal(String id) {
        LambdaQueryWrapper<FeederTopo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FeederTopo::getFeeder, id);
        List<FeederTopo> topoList = feederTopoMapper.selectList(queryWrapper);
        try {
            if (topoList != null && !topoList.isEmpty()) {
                return topoList.stream().filter(a -> !Objects.equals(a.getNormalOpen(), "true"))
                        .map(FeederTopo::getPsrId).collect(Collectors.toList());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Collections.emptyList();
    }

}







