package com.hdkj.lt.core.sys.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.hdkj.lt.base.constants.RedisKeyConstants;
import com.hdkj.lt.core.bizms.modle.po.DwdShbDsFeederBase;
import com.hdkj.lt.core.sys.dao.DwdShbDsFeederBaseMapper;
import com.hdkj.lt.core.sys.model.dto.FeederCacheDTO;
import com.hdkj.lt.core.sys.model.dto.FeederFileDTO;
import com.hdkj.lt.core.sys.model.dto.FhzgDistMappingFileDTO;
import com.hdkj.lt.core.sys.service.DwdShbDsFeederBaseService;
import com.hdkj.lt.utils.cache.RedisRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

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

/**
* @author zhangtj
* @description 针对表【dwd_shb_ds_feeder_base(配电设备_配电馈线台账表)】的数据库操作Service实现
* @createDate 2025-05-24 18:27:00
*/
@Service
@Slf4j
@AllArgsConstructor
public class DwdShbDsFeederBaseServiceImpl extends ServiceImpl<DwdShbDsFeederBaseMapper, DwdShbDsFeederBase>
    implements DwdShbDsFeederBaseService {

    private final RedisRepository redisRepository;

    @Override
    public DwdShbDsFeederBase getByPsrId(String linePsrId) {
        LambdaQueryWrapper<DwdShbDsFeederBase> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DwdShbDsFeederBase::getPsrId, linePsrId);
        List<DwdShbDsFeederBase> list = this.list(wrapper);
        if (CollectionUtils.sizeIsEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    /**
     *
     * @author luorui
     * @date 2025/6/25 14:13
     * @discription 初始化所有线路信息到redis，包括线路对应的图形文件信息
     *
     **/
    @Override
    public Map<String, Object> refreshAllFeederCache() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("refreshAllFeederCache");
        Map<String, Object> cacheDTOMap = new HashMap<>();
        try {
            int limit = 1000;//每次查询1000 条
            int offset = 0;
            List<FeederFileDTO> feederFileDTOList;
            do {
                feederFileDTOList = baseMapper.getFeederFile(limit, offset);
                //批量处理
                processBatch(cacheDTOMap, feederFileDTOList);
                offset += limit;
            } while (feederFileDTOList.size() == limit);
            if (redisRepository.exists(RedisKeyConstants.CACHE_KEY_FEEDER_HASH)) {
                redisRepository.del(RedisKeyConstants.CACHE_KEY_FEEDER_HASH);
            }
            redisRepository.putHashValues(RedisKeyConstants.CACHE_KEY_FEEDER_HASH, cacheDTOMap);
        } catch (RuntimeException ex) {
            throw new RuntimeException(String.format("调用线路信息缓存刷新时发生异常：%s", ex.getMessage()));
        } finally {
            stopWatch.stop();
            log.info("线路信息缓存刷新耗时{}秒", stopWatch.getLastTaskInfo().getTimeSeconds());
        }
        return cacheDTOMap;
    }

    private void processBatch(Map<String, Object> cacheDTOMap, List<FeederFileDTO> feederFileDTOList) {
        if(CollUtil.isEmpty(feederFileDTOList)){
            return;
        }
        //k->psrId   v-> 查询的线路和文件集合
        Map<String,List<FeederFileDTO>> feederFileDTOMap = feederFileDTOList.stream().collect(Collectors.groupingBy(FeederFileDTO::getPsrId));
        //将查询的数据添加到cacheDTOMap中
        feederFileDTOMap.keySet().forEach(k->{
            Object feederCacheDTO = cacheDTOMap.get(k);
            List<FeederFileDTO> fileDTOList = feederFileDTOMap.get(k);
            List<FhzgDistMappingFileDTO> fileList = new ArrayList<>();
            if (null == feederCacheDTO) {
                //cacheDTOMap中不存在psrId
                fileDTOList.stream().filter(e->!Objects.isNull(e.getId())).forEach(e->{
                    FhzgDistMappingFileDTO fhzgDistMappingFileDTO = new FhzgDistMappingFileDTO();
                    BeanUtil.copyProperties(e,fhzgDistMappingFileDTO);//拷贝文件字段信息
                    fhzgDistMappingFileDTO.setLineId(e.getPsrId());
                    fileList.add(fhzgDistMappingFileDTO);
                });
                feederCacheDTO = new FeederCacheDTO();
                BeanUtil.copyProperties(fileDTOList.get(0),feederCacheDTO);//拷贝线路字段信息
                ((FeederCacheDTO)feederCacheDTO).setFileList(fileList);
                cacheDTOMap.put(k, feederCacheDTO);
            } else {
                //cacheDTOMap中已经存在psrId，添加到fileList中
                fileDTOList.forEach(e->{
                    FhzgDistMappingFileDTO fhzgDistMappingFileDTO = new FhzgDistMappingFileDTO();
                    BeanUtil.copyProperties(e,fhzgDistMappingFileDTO);//拷贝文件字段信息
                    fileList.add(fhzgDistMappingFileDTO);
                });
                ((FeederCacheDTO)feederCacheDTO).getFileList().addAll(fileList);//添加到fileList中
            }
        });
    }

    @Override
    public Map<String, FeederCacheDTO> getCacheMapByIds(Collection<String> psrIds) {
        Map<String, FeederCacheDTO> resultMap = Maps.newHashMap();
        if (CollectionUtils.isEmpty(psrIds)) {
            return resultMap;
        }
        Map<String, Object> cacheMap = redisRepository.getHashValue(RedisKeyConstants.CACHE_KEY_FEEDER_HASH);
        psrIds = psrIds.stream().distinct().collect(Collectors.toList());
        psrIds.forEach(i -> Optional.ofNullable(cacheMap.get(i)).ifPresent(e -> resultMap.put(i, (FeederCacheDTO) e)));
        //todo 如果缓存中查询出来的数量少 是否需要查询数据库。还是等下次定时任务刷新缓存后再查询。此处不查数据库保证查询响应速度
        return resultMap;
    }

    /**
     *
     * @author luorui
     * @date 2025/7/1 15:07
     * @discription 优先从缓存获取，没有的话查询数据库，只用于简单场景线路的id和名称的转换。暂时不更新缓存动作
     *
     **/
    @Override
    public FeederCacheDTO getFeederByCacheOrDb(String psrId) {
        if (redisRepository.exists(RedisKeyConstants.CACHE_KEY_FEEDER_HASH)) {
            Map<String, Object> cacheMap = redisRepository.getHashValue(RedisKeyConstants.CACHE_KEY_FEEDER_HASH);
            Object cache = cacheMap.get(psrId);
            if (!Objects.isNull(cache)) {
                return (FeederCacheDTO) cache;
            } else {
                DwdShbDsFeederBase dsFeederBase = getByPsrId(psrId);
                return FeederCacheDTO.builder().name(dsFeederBase.getName()).psrId(dsFeederBase.getPsrId()).build();
            }
        } else {
            DwdShbDsFeederBase dsFeederBase = getByPsrId(psrId);
            return FeederCacheDTO.builder().name(dsFeederBase.getName()).psrId(dsFeederBase.getPsrId()).build();
        }
    }


    @Override
    public Map<String, Object>  getAllFeederCache() {
        if (redisRepository.exists(RedisKeyConstants.CACHE_KEY_FEEDER_HASH)) {
            Map<String, Object> cacheMap = redisRepository.getHashValue(RedisKeyConstants.CACHE_KEY_FEEDER_HASH);
            return cacheMap;
        } else {
            Map<String, Object> cacheMap =  refreshAllFeederCache();
            return cacheMap;
        }
    }

    @Override
    public void refreshFeederCacheById(String feederId) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("refreshFeederCacheById");
        try {
            List<FeederFileDTO> feederCacheList = this.baseMapper.getFeederFileById(feederId);
            if (ObjectUtil.isNotEmpty(feederCacheList)) {
                FeederCacheDTO feederCache = BeanUtil.copyProperties(feederCacheList.get(0), FeederCacheDTO.class);
                feederCache.setFileList(feederCacheList.stream().filter(e -> ObjectUtil.isNotEmpty(e.getFileId()))
                        .map(e -> FhzgDistMappingFileDTO.builder().id(e.getId()).fileId(e.getFileId())
                                .fileType(e.getFileType()).lineId(e.getPsrId()).build()).collect(Collectors.toList()));
                redisRepository.putHashValue(RedisKeyConstants.CACHE_KEY_FEEDER_HASH, feederId, feederCache);
            }
        } catch (RuntimeException ex) {
            throw new RuntimeException(String.format("调用单线路信息缓存刷新时发生异常：%s", ex.getMessage()));
        } finally {
            stopWatch.stop();
            log.info("单线路信息缓存刷新耗时{}秒", stopWatch.getLastTaskInfo().getTimeSeconds());
        }
    }

    @Override
    public List<DwdShbDsFeederBase> getFeederListByMaintOrg(String maintOrg) {
        return this.baseMapper.getFeederListByMaintOrg(maintOrg);
    }
}




