package com.ningdatech.carapi.sys.helper;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.Maps;
import com.ningdatech.carapi.sys.entity.Operator;
import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO;
import com.ningdatech.carapi.sys.manage.OperatorManage;
import com.ningdatech.carapi.sys.mapper.OperatorMapper;
import com.ningdatech.carapi.sys.service.OperatorService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * OperatorsCacheHelper
 * </p>
 *
 * @author PoffyZhang
 * @since 09:01 2022/11/29
 */
@Slf4j
@Component
public class OperatorsCacheHelper implements InitializingBean {

    private LoadingCache<Long, OperatorQueryDTO> operatorCache;

    //==================================================================================================================

    @Autowired
    private OperatorMapper operatorMapper;


    private Map<String,OperatorQueryDTO> operatorNameMap = Maps.newHashMap();

    @Override
    public void afterPropertiesSet() {
        operatorCache = Caffeine.newBuilder()
                //需避免刷新过于频繁
                .refreshAfterWrite(30, TimeUnit.MINUTES)
                .maximumSize(500)
                .build(new CacheLoader<Long, OperatorQueryDTO>() {

                    @Override
                    public OperatorQueryDTO load(Long operatorId) throws Exception {
                        Operator operator = operatorMapper.selectById(operatorId);
                        if(Objects.isNull(operator)){
                            log.info("加载运营商信息失败: 运营商{} 信息为空为空",operatorId);
                            return null;
                        }
                        return BeanUtil.copyProperties(operator, OperatorQueryDTO.class);
                    }

                    @Override
                    public Map<Long, OperatorQueryDTO>  loadAll(Iterable<? extends Long> keys) throws Exception  {
                        List<Operator> operators = operatorMapper.selectList(Wrappers.lambdaQuery(Operator.class).in(Operator::getId,keys));
                        if(CollUtil.isEmpty(operators)){
                            log.info("加载运营商信息失败: 运营商信息为空为空");
                            return Collections.emptyMap();
                        }
                        Map<Long,OperatorQueryDTO> map = operators.stream().map(c->BeanUtil.copyProperties(c, OperatorQueryDTO.class))
                                .collect(Collectors.toMap(OperatorQueryDTO::getId,c -> c));
                        return map;
                    }
                });

        List<Operator> operators = operatorMapper.selectList(Wrappers.lambdaQuery(Operator.class));
        if(CollUtil.isEmpty(operators)){
            log.info("加载运营商信息失败: 运营商为空");
            return;
        }
        operators.stream().forEach(c -> {
            OperatorQueryDTO operator = BeanUtil.copyProperties(c, OperatorQueryDTO.class);
            operatorCache.put(operator.getId(),operator);
            operatorNameMap.put(operator.getName(),operator);
        });
    }

    public Collection<OperatorQueryDTO> all(){
        return operatorCache.asMap().values();
    }

    /**
     * 获取当前运营商信息
     * @param id
     * @return
     */
    public OperatorQueryDTO getById(Long id) {
        return operatorCache.get(id);
    }

    public void refresh(Long id) {
        operatorCache.refresh(id);
        OperatorQueryDTO data = operatorCache.get(id);
        if(Objects.nonNull(data)){
            operatorNameMap.put(data.getName(),data);
        }
    }

    public void refresh(List<Long> ids) {
        if(CollUtil.isNotEmpty(ids)){
            ids.forEach(id -> {
                operatorCache.refresh(id);
                OperatorQueryDTO data = operatorCache.get(id);
                if(Objects.nonNull(data)){
                    operatorNameMap.put(data.getName(),data);
                }
            });
        }
    }

    /**
     * 获取当前运营商名字
     * @param id
     * @return
     */
    public String getNameById(Long id) {
        if(Objects.isNull(id)){
            return StringUtils.EMPTY;
        }
        if(Objects.nonNull(operatorCache.get(id))){
            return operatorCache.get(id).getName();
        }
        return id + StringUtils.EMPTY;
    }

    /**
     * 获取当前运营商信息
     * @param name
     * @return
     */
    public OperatorQueryDTO getByName(String name) {
        return operatorNameMap.get(name);
    }

    /**
     * 获取运营商信息s
     * @return
     */
    public Map<Long,OperatorQueryDTO> asMap() {
        return operatorCache.asMap();
    }
}
