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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultAwaitTransferUsers;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultTransferScheme;
import com.hdkj.lt.modle.dto.jsty.*;
import com.hdkj.lt.mq.mapper.fault.FaultAwaitTransferAreaResultMapper;
import com.hdkj.lt.mq.mapper.fault.FhzgFaultAnalyzeCalculateDecudeMapper;
import com.hdkj.lt.mq.service.fault.AnalysisFaultTransferSchemeService;
import com.hdkj.lt.mq.service.fault.IFaultTransferSchemeService;
import com.hdkj.lt.utils.math.DecimalUtils;
import com.hdkj.lt.utils.security.StrConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author luorui
 * @date 2025/5/24 17:28
 * 解析计算推演平台数据并落库业务表
 */
@Service
@Slf4j
public class AnalysisFaultTransferSchemeServiceImpl implements AnalysisFaultTransferSchemeService {

    @Autowired
    IFaultTransferSchemeService fhzgFaultTransferSchemeService;

    @Autowired
    FaultAwaitTransferAreaResultMapper awaitTransferAreaResultMapper;

    @Autowired
    FhzgFaultAnalyzeCalculateDecudeMapper fhzgFaultAnalyzeCalculateDecudeMapper;

    /**
     * @author luorui
     * @date 2025/5/24 18:07
     * @discription 解析大对象终的转供方案落库
     **/
    public void analysisFaultTransferScheme(Long faultId, Map<Long, XferPlanDTO> xferFaultMap, List<FaultAwaitTransferUsers> awaitTransferUsers) {
        // 生成方案前需要覆盖方案相关级联数据
        //fhzgFaultAnalyzeCalculateDecudeMapper.deleteTransferSchemeAndLinkInfoByFaultId(faultId);
        deleteTransferSchemeAndLinkInfoByFaultId(faultId);

        //返回保存的主键和 计划的对象
//        Map<Long,XferPlanDTO> idXferFaultDTOMap = new HashMap<>();
        List<FaultTransferScheme> fhzgFaultTransferSchemeList = new ArrayList<>();
        for (Long schemeId : xferFaultMap.keySet()) {
            XferPlanDTO xferFaultDTO = xferFaultMap.get(schemeId);
            List<List<BreakerInfoDTO>> breakerOperationOrderList = xferFaultDTO.getBreakerOperationOrderListList();//开关动作顺序数据
            Integer switchOperationCount = 0;
            Integer nonAutoSwitchOperationCount = 0;
            if (CollUtil.isNotEmpty(breakerOperationOrderList)) {
                for (List<BreakerInfoDTO> list : breakerOperationOrderList) {
                    for (BreakerInfoDTO breaker : list) {
                        if (!StringUtils.equals("auto3Y", breaker.getAutoType())) {
                            nonAutoSwitchOperationCount++;
                        }
                        switchOperationCount++;
                    }
                }
            }
            List<XferSupplyAreaDTO> xferSupplyAreaList = xferFaultDTO.getXferSupplyAreaList(); // 转供方案开关及设备区域信息

            FaultTransferScheme faultTransferScheme = new FaultTransferScheme();
            faultTransferScheme.setFaultId(faultId);//计划编码
            faultTransferScheme.setSchemeState("02");//方案选择状态默认 "02" 未选定
            faultTransferScheme.setSwitchOperationCount(String.format("%s/%s", nonAutoSwitchOperationCount, switchOperationCount));//开关动作次数(计算推演平台breakerOperationInfo动作开关计数)
            this.setCountValue(faultTransferScheme, xferSupplyAreaList, awaitTransferUsers);
            faultTransferScheme.setCreateTime(LocalDateTime.now());
            faultTransferScheme.setId(schemeId);
            faultTransferScheme.setRowJson(JSON.toJSONString(xferFaultDTO));
//            idXferFaultDTOMap.put(faultTransferScheme.getId(),xferFaultDTO);

            fhzgFaultTransferSchemeList.add(faultTransferScheme);
        }
        // 根据最大负载率 升序 取前十
        AtomicInteger index = new AtomicInteger(1);
        List<FaultTransferScheme> transferSchemesList = fhzgFaultTransferSchemeList.stream()
                .sorted(Comparator.comparing(FaultTransferScheme::getFaultMaxCurrentLoad))
                .map(e -> e.setSchemeName(String.format("方案%s", StrConvertUtils.toChineseStr(index.getAndIncrement()))))//方案编码
                .limit(10).collect(Collectors.toList());

        fhzgFaultTransferSchemeService.saveBatch(transferSchemesList);
    }

    //转供方案的子区域,设置统计字段
    private void setCountValue(FaultTransferScheme fhzgFaultTransferScheme, List<XferSupplyAreaDTO> xferSupplyAreaList, List<FaultAwaitTransferUsers> awaitTransferUsers) {
        Integer lossUser = null;//损失用户，为不可转供区域的 中压用户和公变用户的数量之和
        //如果没有不可转供区域则 lossUser 为 0
        //计算是否为推荐方案
        boolean schemeCheck = true; //只要有一个区域的 对侧负荷大于100%则不是推荐方案
        //收集可转供 中压用户和公变用户 psrId集合 ,从待转供用户中筛选出 对应用户，累计转供前的用户负荷
        List<String> userList = new ArrayList<>();
        for (XferSupplyAreaDTO dto : xferSupplyAreaList) {
            //不可转区域用户信息,损失户数
            AreaDeviceDTO areaDeviceInfo = dto.getAreaDeviceInfo();
            if (!Objects.equals(dto.getPowerOnSuccess(), Boolean.TRUE)) {
                //如果推演平台数据有问题，有不可转供区域但是 公变和中压信息为 null
                Integer countMvTransList = CollUtil.isEmpty(areaDeviceInfo.getMvTransList()) ? null : areaDeviceInfo.getMvTransList().size();
                Integer countMvCustomerList = CollUtil.isEmpty(areaDeviceInfo.getMvCustomerList()) ? null : areaDeviceInfo.getMvCustomerList().size();
                if (countMvTransList != null || countMvCustomerList != null) {
                    lossUser = (countMvTransList == null ? 0 : countMvTransList) + (countMvCustomerList == null ? 0 : countMvCustomerList);
                }
            } else {
                //可转供区域用户信息,中压用户和公变用户  中压光伏列表
                if (areaDeviceInfo != null) {
                    // 公变信息列表
                    List<TransCustomerDTO> mvTransList = areaDeviceInfo.getMvTransList();
                    if (CollUtil.isNotEmpty(mvTransList)) {
                        List<String> psrIdList = mvTransList.stream().filter(e -> StrUtil.isNotBlank(e.getPsrID())).map(TransCustomerDTO::getPsrID).collect(Collectors.toList());
                        userList.addAll(psrIdList);
                    }
                    // 中压用户列表
                    List<TransCustomerDTO> mvCustomerList = areaDeviceInfo.getMvCustomerList();
                    if (CollUtil.isNotEmpty(mvCustomerList)) {
                        List<String> psrIdList = mvCustomerList.stream().filter(e -> StrUtil.isNotBlank(e.getPsrID())).map(TransCustomerDTO::getPsrID).collect(Collectors.toList());
                        userList.addAll(psrIdList);
                    }
                }
            }
            Double faultMaxCurrentLoad = Optional.ofNullable(dto.getLinkLineInfo()).map(LinkLineDTO::getPlanMaxCurrentLoad).orElse(null);//线路出来最大负载（%）
            // 设置最大负载率，用来筛选升序前十条数据, 当值为空时确保排序靠后
            fhzgFaultTransferScheme.setFaultMaxCurrentLoad(Optional.ofNullable(faultMaxCurrentLoad).map(BigDecimal::valueOf).orElse(BigDecimal.valueOf(200.0)));
            if (faultMaxCurrentLoad != null && faultMaxCurrentLoad > 100) {
                //todo  对方传值为空怎么处理
                schemeCheck = false;
            }
        }
        //方案中的不可转供区域如果没有的话 损失户数为 0
        Long nonArea = xferSupplyAreaList.stream().filter(e -> !Objects.equals(e.getPowerOnSuccess(), Boolean.TRUE)).count();
        if (Objects.equals(nonArea, 0L)) {
            lossUser = 0;//前面可能为空
        }
        //从待转供用户中筛选出来可转供的用户 用来计算可转供负荷和 转供总负荷
        double userTransferSum = awaitTransferUsers.stream()
                .filter(en -> userList.contains(en.getTransformerNo()) && ObjectUtils.isNotEmpty(en.getUserLoads()))
                .map(en -> en.getUserLoads()).mapToDouble(BigDecimal::doubleValue).sum();
        BigDecimal userTransferSumBigDecimal = BigDecimal.valueOf(userTransferSum).setScale(6, RoundingMode.HALF_UP);
        double totalTransferSum = awaitTransferUsers.stream()
                .filter(en -> ObjectUtils.isNotEmpty(en.getUserLoads()))
                .map(en -> en.getUserLoads()).mapToDouble(BigDecimal::doubleValue).sum();
        BigDecimal totalTransferSumBigDecimal = BigDecimal.valueOf(totalTransferSum).setScale(6, RoundingMode.HALF_UP);

        fhzgFaultTransferScheme.setFeasibleTransfer(userTransferSumBigDecimal);//可行的转供负荷数
        fhzgFaultTransferScheme.setTotalTransfer(totalTransferSumBigDecimal);//转供总负荷数
        fhzgFaultTransferScheme.setLoadRecovery((DecimalUtils.divide(totalTransferSumBigDecimal, userTransferSumBigDecimal, 4, RoundingMode.HALF_UP)).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP));//负荷恢复
        fhzgFaultTransferScheme.setLossCustHours(lossUser == null ? null : new BigDecimal(lossUser)); //损失时户
        fhzgFaultTransferScheme.setLossUsers(lossUser); //损失时户

        fhzgFaultTransferScheme.setSchemeCheck(schemeCheck ? "1" : "0");//scheme_check	方案校验结果(1-通过，0-不通过)
    }

    /**
     * 删除故障场景事件相关表信息
     *
     * @param faultId
     */
    public void deleteTransferSchemeAndLinkInfoByFaultId(Long faultId) {
        // 先删依赖 switching 的
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteSwitchingLoopCheckByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteSwitchingFinalCheckByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteLoopSwCurrentDetailByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteLoopSegCurrentDetailByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteFinalSwCurrentDetailByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteFinalSegCurrentDetailByFaultId(faultId);

        // 再删 switching_sequence
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteSwitchingSequenceByFaultId(faultId);

        // 删除其他关联表
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteBreakerSvgAfterByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deletePathDetailByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteOppositeLineLoadFactorByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteSchemeUsersByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteTransferableSchemeUsersByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteOppositeLineConcatSwitchByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteEvaluationIndexByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteStrategyScoreByFaultId(faultId);

        // 删除直接按 fault_id 关联的
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteCarryCapacityByFaultId(faultId);
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteAwaitTransferUsersByFaultId(faultId);

        // 最后删主表
        fhzgFaultAnalyzeCalculateDecudeMapper.deleteTransferSchemeByFaultId(faultId);
    }

}
