package com.ningdatech.carapi.sys.helper;

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.car.vehicle.model.NdVehicleBaseInfo;
import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

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

    private LoadingCache<Long, NdVehicleBaseInfo> vehicleCache;

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

    private Map<String, NdVehicleBaseInfo> vehicleMap = Maps.newHashMap();
    private Map<String, NdVehicleBaseInfo> carPlateMap = Maps.newHashMap();

    @Resource
    private VehicleBaseInfoMapper vehicleBaseInfoMapper;

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

                    @Override
                    public NdVehicleBaseInfo load(Long id) throws Exception {
                        NdVehicleBaseInfo vehicle = vehicleBaseInfoMapper.selectById(id);
                        if(Objects.isNull(vehicle)){
                            log.info("加载车辆信息失败: 车辆{} 信息为空为空",id);
                            return null;
                        }
                        return vehicle;
                    }

                    @Override
                    public Map<Long, NdVehicleBaseInfo>  loadAll(Iterable<? extends Long> keys) throws Exception  {
                        List<NdVehicleBaseInfo> vehicles = vehicleBaseInfoMapper.selectList(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).in(NdVehicleBaseInfo::getId,keys));
                        if(CollUtil.isEmpty(vehicles)){
                            log.info("加载车辆信息失败: 车辆信息为空为空");
                            return Collections.emptyMap();
                        }
                        Map<Long,NdVehicleBaseInfo> map = vehicles.stream()
                                .collect(Collectors.toMap(c -> c.getId(),c -> c));
                        return map;
                    }


                });

        List<NdVehicleBaseInfo> vehicles = vehicleBaseInfoMapper.selectList(Wrappers.lambdaQuery(NdVehicleBaseInfo.class));
        if(CollUtil.isEmpty(vehicles)){
            log.info("加载车辆信息失败: 车辆为空");
            return;
        }
        vehicles.stream().forEach(v -> {
            vehicleCache.put(v.getId(),v);
            vehicleMap.put(v.getCompanyId() + v.getCarPlate(),v);
            carPlateMap.put(v.getCarPlate(),v);
        });
    }

    public Collection<NdVehicleBaseInfo> all(){
        return vehicleCache.asMap().values();
    }

    /**
     * 获取当前车辆信息
     * @param id
     * @return
     */
    public NdVehicleBaseInfo getById(Long id) {
        return vehicleCache.get(id);
    }

    /**
     * 获取当前车辆信息 企业ID和车牌号
     * @param companyCarPlate
     * @return
     */
    public NdVehicleBaseInfo getByCompanyCarPlate(String companyCarPlate) {
        return vehicleMap.get(companyCarPlate);
    }
    public NdVehicleBaseInfo getByCarPlate(String carPlate) {
        return carPlateMap.get(carPlate);
    }

    public Boolean isExits(String carPlate) {
        return carPlateMap.containsKey(carPlate);
    }

    /**
     * 获取当前车辆信息
     * @return
     */
    public Map<Long,NdVehicleBaseInfo> asMap() {
        return vehicleCache.asMap();
    }

    public void refresh(Long id) {
        vehicleCache.refresh(id);
        NdVehicleBaseInfo vehicleBaseInfo = vehicleCache.get(id);
        if(Objects.nonNull(vehicleBaseInfo)){
            vehicleMap.put(vehicleBaseInfo.getCompanyId() + vehicleBaseInfo.getCarPlate(),vehicleBaseInfo);
            carPlateMap.put(vehicleBaseInfo.getCarPlate(),vehicleBaseInfo);
        }
    }

    public void refresh(List<Long> ids) {
        if(CollUtil.isNotEmpty(ids)){
            ids.forEach(id -> {
                vehicleCache.refresh(id);
                NdVehicleBaseInfo vehicleBaseInfo = vehicleCache.get(id);
                if(Objects.nonNull(vehicleBaseInfo)){
                    vehicleMap.put(vehicleBaseInfo.getCompanyId() + vehicleBaseInfo.getCarPlate(),vehicleBaseInfo);
                    carPlateMap.put(vehicleBaseInfo.getCarPlate(),vehicleBaseInfo);
                }
            });
        }
    }
}
