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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdkj.lt.base.exception.BusinessException;
import com.hdkj.lt.bf.constants.TransferSchemeConstants;
import com.hdkj.lt.bf.entity.dto.FhzgFaultTransferSchemeCheckCountResultDTO;
import com.hdkj.lt.bf.entity.dto.FhzgFaultTransferSchemeDTO;
import com.hdkj.lt.bf.entity.dto.FhzgFaultTransferSchemeTransferSituationDTO;
import com.hdkj.lt.bf.entity.dto.FhzgFaultTransferSchemeUpdateReqDTO;
import com.hdkj.lt.bf.mapper.FaultTransferSchemeMapper;
import com.hdkj.lt.bf.service.IFaultAwaitTransferUsersService;
import com.hdkj.lt.bf.service.IFaultPowerCutService;
import com.hdkj.lt.bf.service.IFaultTransferSchemeService;
import com.hdkj.lt.bf.service.IFaultTransferSchemeUsersService;
import com.hdkj.lt.core.bizms.modle.dto.TransferSchemeEvaluationReqDTO;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultAwaitTransferUsers;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultPowerCut;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultTransferScheme;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultTransferSchemeUsers;
import com.hdkj.lt.modle.dto.jsty.AllSwitchInfoListDTO;
import com.hdkj.lt.modle.dto.jsty.XferPlanDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 故障停电转供方案信息表 服务实现类
 * </p>
 *
 * @author luorui
 * @since 2025-05-29
 */
@Slf4j
@Service
public class FaultTransferSchemeServiceImpl extends ServiceImpl<FaultTransferSchemeMapper, FaultTransferScheme> implements IFaultTransferSchemeService {


    @Autowired
    IFaultPowerCutService faultPowerCutService;

    @Autowired
    IFaultAwaitTransferUsersService fhzgFaultAwaitTransferUsersService;

    @Autowired
    IFaultTransferSchemeUsersService fhzgFaultTransferSchemeUsersService;
    @Autowired
    FaultTransferSchemeMapper faultTransferSchemeMapper;

    /**
     * @author luorui
     * @date 2025/5/26 16:59
     * @discription 查询方案的转供情况
     **/
    @Override
    public FhzgFaultTransferSchemeTransferSituationDTO getTransferSchemeSituationById(TransferSchemeEvaluationReqDTO transferSchemeEvaluationReqDTO) {
        Long faultId = transferSchemeEvaluationReqDTO.getFaultId();
        Long schemeId = transferSchemeEvaluationReqDTO.getSchemeId();
        if (Objects.isNull(faultId)) {
            throw new BusinessException("计划编码不能为空FaultId");
        }
        if (Objects.isNull(schemeId)) {
            throw new BusinessException("方案编码不能为空schemeId");
        }
        //1.查询待转供用户信息
        //2.查询损失用户信息
        //3.待转供数据 - 损失的数据 = 可转供的数据
        Map<String, Object> FaultIdColumnMap = new HashMap<>();
        FaultIdColumnMap.put("fault_id", faultId);
        List<FaultAwaitTransferUsers> awaitTransferUserList = fhzgFaultAwaitTransferUsersService.getBaseMapper().selectByMap(FaultIdColumnMap);
        Map<String, Object> schemeIdColumnMap = new HashMap<>();
        schemeIdColumnMap.put("scheme_id", schemeId);
        List<FaultTransferSchemeUsers> schemeUsersList = fhzgFaultTransferSchemeUsersService.getBaseMapper().selectByMap(schemeIdColumnMap);

        //方案的损失用户(不可转供户数)
        Long loseUsers = schemeUsersList.stream().filter(e -> StrUtil.equals(e.getDataType(), "1")).count();
        //不可转供负荷
        BigDecimal loseLoad = schemeUsersList.stream().filter(e -> StrUtil.equals(e.getDataType(), "1")).filter(e -> !Objects.isNull(e.getActivePower())).map(FaultTransferSchemeUsers::getActivePower).reduce(BigDecimal.ZERO, BigDecimal::add);
        //不可转供重要用户
        Long nonCriticalUser = schemeUsersList.stream().filter(e -> StrUtil.equals(e.getDataType(), "1") && StrUtil.equals(e.getIsCriticalUser(), "1")).count();
        //不可转供重要用户负荷
        BigDecimal nonCriticalUserLoad = schemeUsersList.stream().filter(e -> StrUtil.equals(e.getDataType(), "1") && StrUtil.equals(e.getIsCriticalUser(), "1")).filter(e -> !Objects.isNull(e.getActivePower())).map(FaultTransferSchemeUsers::getActivePower).reduce(BigDecimal.ZERO, BigDecimal::add);
        //不可转供敏感用户
        Long nonSensitiveUser = schemeUsersList.stream().filter(e -> StrUtil.equals(e.getDataType(), "1") && StrUtil.equals(e.getIsSensitiveUser(), "1")).count();
        //不可转供敏感用户负荷
        BigDecimal nonSensitiveUserLoad = schemeUsersList.stream().filter(e -> StrUtil.equals(e.getDataType(), "1") && StrUtil.equals(e.getIsSensitiveUser(), "1")).filter(e -> !Objects.isNull(e.getActivePower())).map(FaultTransferSchemeUsers::getActivePower).reduce(BigDecimal.ZERO, BigDecimal::add);
        //可转供重要用户  待转供重要用户-不可转供重要
        Long awaitCriticalUser = awaitTransferUserList.stream().filter(e -> StrUtil.equals(e.getIsCriticalUser(), "1")).count();
        Long canCriticalUser = awaitCriticalUser - nonCriticalUser;
        //可转供重要用户 负荷  待转供重要负荷-损失重要负荷
        BigDecimal awaitCriticalLoad = awaitTransferUserList.stream().filter(e -> StrUtil.equals(e.getIsCriticalUser(), "1")).filter(e -> !Objects.isNull(e.getUserLoads())).map(FaultAwaitTransferUsers::getUserLoads).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal canCriticalLoad = awaitCriticalLoad == null ? null : awaitCriticalLoad.subtract(nonCriticalUserLoad);

        //可转供敏感用户 待转供敏感用户-不可转供敏感
        Long awaitSensitiveUser = awaitTransferUserList.stream().filter(e -> StrUtil.equals(e.getIsSensitiveUser(), "1")).count();
        Long canSensitiveUser = awaitSensitiveUser - nonSensitiveUser;

        //可转供敏感用户 负荷  待转供敏感负荷-损失敏感负荷
        BigDecimal awaitSensitiveLoad = awaitTransferUserList.stream().filter(e -> StrUtil.equals(e.getIsSensitiveUser(), "1")).filter(e -> !Objects.isNull(e.getUserLoads())).map(FaultAwaitTransferUsers::getUserLoads).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal canSensitiveLoad = awaitSensitiveLoad == null ? null : awaitSensitiveLoad.subtract(nonSensitiveUserLoad);

        //可转供户数 待转供用户-损失用户
        Integer awaitUsers = awaitTransferUserList.size();
        Long canTransferUser = awaitUsers - loseUsers;
        //可转供负荷 待转供负荷-损失负荷
        BigDecimal awaitLoad = awaitTransferUserList.stream().filter(e -> !Objects.isNull(e.getUserLoads())).map(FaultAwaitTransferUsers::getUserLoads).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal canLoad = awaitLoad == null ? null : awaitLoad.subtract(loseLoad);

        //不可转供保电用户数
        Long nonProtectUser = schemeUsersList.stream().filter(e -> StrUtil.equals(e.getDataType(), "1") && StrUtil.equals(e.getIsProtectPower(), "1")).count();
        //不可转供保电用户负荷
        BigDecimal nonProtectLoad = schemeUsersList.stream().filter(e -> StrUtil.equals(e.getDataType(), "1") && StrUtil.equals(e.getIsProtectPower(), "1")).filter(e -> !Objects.isNull(e.getActivePower())).map(FaultTransferSchemeUsers::getActivePower).reduce(BigDecimal.ZERO, BigDecimal::add);

        //可转供保电用户数
        Long canTansferProtectUsers = awaitTransferUserList.stream().filter(e -> StrUtil.equals(e.getIsProtectPower(), "1")).count() - nonProtectUser;
        //可转供保电用户负荷
        BigDecimal canTansferProtectLoad = awaitTransferUserList.stream().filter(e -> StrUtil.equals(e.getIsProtectPower(), "1")).filter(e -> !Objects.isNull(e.getUserLoads())).map(FaultAwaitTransferUsers::getUserLoads).reduce(BigDecimal.ZERO, BigDecimal::add).subtract(nonProtectLoad);


        FhzgFaultTransferSchemeTransferSituationDTO fhzgfaultTransferSchemeTransferSituationDTO = new FhzgFaultTransferSchemeTransferSituationDTO();
        fhzgfaultTransferSchemeTransferSituationDTO.setTransferableLoad(canLoad.multiply(new BigDecimal("1000")));//可转供负荷
        fhzgfaultTransferSchemeTransferSituationDTO.setTransferableUsers(canTransferUser == null ? 0 : canTransferUser.intValue());//可转供户数
        fhzgfaultTransferSchemeTransferSituationDTO.setSensitiveTransferableLoad(canSensitiveLoad.multiply(new BigDecimal("1000"))); //可转供敏感用户负荷
        fhzgfaultTransferSchemeTransferSituationDTO.setSensitiveTransferableUsers(canSensitiveUser == null ? 0 : canSensitiveUser.intValue()); //可转供敏感户数
        fhzgfaultTransferSchemeTransferSituationDTO.setImportantTransferableLoad(canCriticalLoad.multiply(new BigDecimal("1000")));//可转供重要负荷
        fhzgfaultTransferSchemeTransferSituationDTO.setImportantTransferableUsers(canCriticalUser == null ? 0 : canCriticalUser.intValue()); //可转供重要户数
        fhzgfaultTransferSchemeTransferSituationDTO.setNonTransferableLoad(loseLoad.multiply(new BigDecimal("1000"))); //不可转供负荷
        fhzgfaultTransferSchemeTransferSituationDTO.setNonTransferableUsers(loseUsers == null ? 0 : loseUsers.intValue());//不可转供户数
        fhzgfaultTransferSchemeTransferSituationDTO.setSensitiveNonTransferableLoad(nonSensitiveUserLoad.multiply(new BigDecimal("1000")));//不可转供敏感用户负荷
        fhzgfaultTransferSchemeTransferSituationDTO.setSensitiveNonTransferableUsers(nonSensitiveUser == null ? 0 : nonSensitiveUser.intValue());//不可转供敏感户数
        fhzgfaultTransferSchemeTransferSituationDTO.setImportantNonTransferableLoad(nonCriticalUserLoad.multiply(new BigDecimal("1000"))); //不可转供重要负荷
        fhzgfaultTransferSchemeTransferSituationDTO.setImportantNonTransferableUsers(nonCriticalUser == null ? 0 : nonCriticalUser.intValue());  //不可转供重要户数

        fhzgfaultTransferSchemeTransferSituationDTO.setSecuredTransferableUsers(canTansferProtectUsers == null ? 0 : canTansferProtectUsers.intValue());
        fhzgfaultTransferSchemeTransferSituationDTO.setSecuredTransferableLoad(canTansferProtectLoad.multiply(new BigDecimal("1000")));
        fhzgfaultTransferSchemeTransferSituationDTO.setSecuredNonTransferableUsers(nonProtectUser == null ? 0 : nonProtectUser.intValue());
        fhzgfaultTransferSchemeTransferSituationDTO.setSecuredNonTransferableLoad(nonProtectLoad.multiply(new BigDecimal("1000")));


        fhzgfaultTransferSchemeTransferSituationDTO.setSchemeId(schemeId);
        //损失户数
        fhzgfaultTransferSchemeTransferSituationDTO.setLoseUsers(loseUsers);
        return fhzgfaultTransferSchemeTransferSituationDTO;
    }

    /**
     * @author luorui
     * @date 2025/5/29 21:57
     * @discription 查询列表
     **/
    @Override
    public List<FhzgFaultTransferSchemeDTO> getTransferSchemeListByFaultId(FaultTransferScheme fhzgFaultTransferScheme) {
        Long faultId = fhzgFaultTransferScheme.getFaultId();
        String schemeType = fhzgFaultTransferScheme.getSchemeType();
        if (Objects.isNull(faultId)) {
            throw new BusinessException("计划编码不能为空");
        }
        log.info("查询请求参数FaultId：{}，schemeType：{}", faultId, schemeType);
        /**1.根据计划和方案类型（推荐方案/校验失败方案）查询出组合方案id集合*/
        List<FhzgFaultTransferSchemeDTO> fhzgFaultTransferSchemeDTOList = baseMapper.getFhzgFaultTransferSchemeByFaultId(fhzgFaultTransferScheme);
        fhzgFaultTransferSchemeDTOList.forEach(i->{
            i.setTotalTransfer(i.getTotalTransfer().multiply(new BigDecimal("1000")));
            i.setFeasibleTransfer(i.getFeasibleTransfer().multiply(new BigDecimal("1000")));
        });
        return fhzgFaultTransferSchemeDTOList;
    }

    /**
     * @author luorui
     * @date 2025/5/29 22:09
     * @discription 查询方案校验通过不通过数量
     **/
    @Override
    public List<FhzgFaultTransferSchemeCheckCountResultDTO> getTransferSchemeCheckResultCountByFaultId(FaultTransferScheme fhzgFaultTransferScheme) {
        if (Objects.isNull(fhzgFaultTransferScheme.getFaultId())) {
            throw new BusinessException("故障停电faultId为空");
        }
        List<FhzgFaultTransferSchemeCheckCountResultDTO> countResultDTOList = new ArrayList<>();
        FhzgFaultTransferSchemeCheckCountResultDTO resultSafe = new FhzgFaultTransferSchemeCheckCountResultDTO();
        resultSafe.setSchemeCheck(TransferSchemeConstants.SchemeType.SAFE);
        resultSafe.setCount(0);
        countResultDTOList.add(resultSafe);
        FhzgFaultTransferSchemeCheckCountResultDTO resultUnsafe = new FhzgFaultTransferSchemeCheckCountResultDTO();
        resultUnsafe.setSchemeCheck(TransferSchemeConstants.SchemeType.UNSAFE);
        resultUnsafe.setCount(0);
        countResultDTOList.add(resultUnsafe);
        //方案类型schemeType：1-推荐方案，0-校验失败方案。判断方式：区域方案只要有一个方案安全校验通过则组合方案为推荐方案，否则为校验失败方案
        List<FhzgFaultTransferSchemeCheckCountResultDTO> fhzgFaultTransferSchemeCheckResultDTOList = baseMapper.countSchemeCheckByFaultId(fhzgFaultTransferScheme);
        if (CollUtil.isNotEmpty(fhzgFaultTransferSchemeCheckResultDTOList)) {
            Map<String, Integer> countResultMap = fhzgFaultTransferSchemeCheckResultDTOList.stream().collect(Collectors.toMap(FhzgFaultTransferSchemeCheckCountResultDTO::getSchemeCheck, FhzgFaultTransferSchemeCheckCountResultDTO::getCount, (k1, k2) -> k1));
            countResultDTOList.forEach(e -> {
                Integer count = countResultMap.get(e.getSchemeCheck());
                e.setCount(Objects.isNull(count) ? 0 : count);
            });
        }
        return countResultDTOList;
    }

    /**
     * @author luorui
     * @date 2025/5/29 22:25
     * @discription 修改方案状态
     **/
    @Override
    public Integer updateSchemeState(FhzgFaultTransferSchemeUpdateReqDTO faultTransferSchemeUpdateReqDTO) {
        Long id = faultTransferSchemeUpdateReqDTO.getId();
        Long faultId = faultTransferSchemeUpdateReqDTO.getFaultId();
        String schemeState = faultTransferSchemeUpdateReqDTO.getSchemeState();
        if (Objects.isNull(id)) {
            throw new BusinessException("主键不能为空");
        }
        if (Objects.isNull(faultId)) {
            throw new BusinessException("故障id不能为空");
        }
        if (StrUtil.isBlank(schemeState)) {
            throw new BusinessException("方案选定状态不能为空");
        }
        Integer result = 0;
        switch (schemeState) {
            case TransferSchemeConstants.SchemeState.UN_CHOOSE:
                /**1如果是选定切换成未选定，更新当前这条数据*/
                result = faultTransferSchemeMapper.updateFhzgFaultTransferSchemeState(id, schemeState);
                //更新计划的方案状态为"未选定"
                updateSchemeState(faultId, TransferSchemeConstants.SchemeState.UN_CHOOSE);
                break;
            case TransferSchemeConstants.SchemeState.CHOOSE:
                result = faultTransferSchemeMapper.updateFhzgFaultTransferSchemeState(id, schemeState);//更新当前方案为选定
                /**2.查询计划下的所有校验通过的组合方案Id*/
                FaultTransferScheme fhzgFaultTransferScheme = new FaultTransferScheme();
                fhzgFaultTransferScheme.setFaultId(faultId);
                List<FhzgFaultTransferSchemeDTO> fhzgFaultTransferSchemeCheckResultDTOList = faultTransferSchemeMapper.getFhzgFaultTransferSchemeByFaultId(fhzgFaultTransferScheme);
                if (CollUtil.isNotEmpty(fhzgFaultTransferSchemeCheckResultDTOList)) {
                    Set<Long> idSet = fhzgFaultTransferSchemeCheckResultDTOList.stream().map(FhzgFaultTransferSchemeDTO::getId).collect(Collectors.toSet());
                    /** 3.如果是未选定切换成选定，更新当前数据为选定，同事更新其他数据为未选定*/
                    idSet.remove(id);//排除当前id
                    //更新其他方案为未选定
                    if (CollUtil.isNotEmpty(idSet)) {
                        faultTransferSchemeMapper.updateFhzgFaultTransferSchemeStateBatch(idSet, TransferSchemeConstants.SchemeState.UN_CHOOSE);
                    }
                }
                //更新计划的方案状态为"已选定"
                updateSchemeState(faultId, TransferSchemeConstants.SchemeState.CHOOSE);
                break;
            default:
                throw new BusinessException("方案选定状态不能枚举不正确");
        }
        return result;
    }


    private Integer updateSchemeState(Long FaultId, String schemeState) {
        FaultPowerCut obj = new FaultPowerCut();
        obj.setId(FaultId);
        obj.setSchemeState(schemeState);
        return faultPowerCutService.updateSchemeState(obj);
    }

    @Override
    public List<AllSwitchInfoListDTO> getAllSwitchBySchemeId(Long schemeId) {
        FaultTransferScheme faultTransferScheme = this.getById(schemeId);
        String rowJson = faultTransferScheme.getRowJson();
        XferPlanDTO xferPlanDTO = JSON.parseObject(rowJson, XferPlanDTO.class);
        return xferPlanDTO.getAllSwitchInfoList();
    }
}
