package cn.lihongjie.coal.cacheCtl.service;

import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.cacheCtl.dto.CacheCtlDto;
import cn.lihongjie.coal.cacheCtl.dto.CreateCacheCtlDto;
import cn.lihongjie.coal.cacheCtl.dto.UpdateCacheCtlDto;
import cn.lihongjie.coal.cacheCtl.entity.CacheCtlEntity;
import cn.lihongjie.coal.cacheCtl.mapper.CacheCtlMapper;
import cn.lihongjie.coal.cacheCtl.repository.CacheCtlRepository;
import cn.lihongjie.coal.exception.BizException;

import com.google.common.base.Splitter;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class CacheCtlService extends BaseService<CacheCtlEntity, CacheCtlRepository> {
    @Autowired CacheManager cacheManager;
    @Autowired RedisTemplate<String, String> redisTemplate;
    @Autowired private CacheCtlRepository repository;
    @Autowired private CacheCtlMapper mapper;
    @Autowired private ConversionService conversionService;

    public CacheCtlDto create(CreateCacheCtlDto request) {
        throw new BizException("不支持更新操作");
    }

    public CacheCtlDto update(UpdateCacheCtlDto request) {

        throw new BizException("不支持更新操作");
    }

    public void delete(IdRequest request) {

        cacheManager.getCache(request.getId()).invalidate();
    }

    public void deleteKey(CacheCtlDto request) {

        cacheManager.getCache(request.getId()).evictIfPresent(request.getCacheKey());
    }

    public CacheCtlDto getById(String id) {
        CacheCtlEntity entity = repository.get(id);

        return mapper.toDto(entity);
    }

    public Page<CacheCtlDto> list(CommonQuery query) {

        List<CacheCtlDto> collect =
                cacheManager.getCacheNames().stream()
                        .map(
                                cacheName -> {
                                    CacheCtlDto dto = new CacheCtlDto(cacheName);
                                    dto.setId(cacheName);

                                    return dto;
                                })
                        .collect(Collectors.toList());
        return new PageImpl<>(
                collect, PageRequest.of(query.getPageNo(), query.getPageSize()), collect.size());
    }

    public List<CacheCtlDto> keys(CacheCtlDto request) {

        Set<String> keys = redisTemplate.keys(request.getCacheName() + "::*");

        return keys.stream()
                .map(
                        x -> {
                            CacheCtlDto dto = new CacheCtlDto(request.getId());
                            dto.setId(request.getId());
                            dto.setCacheKey(
                                    Splitter.on("::")
                                            .trimResults()
                                            .omitEmptyStrings()
                                            .splitToList(x)
                                            .get(1));
                            return dto;
                        })
                .collect(Collectors.toList());
    }

    public CacheCtlDto value(CacheCtlDto request) {

        request.setCacheValue(
                redisTemplate
                        .opsForValue()
                        .get(request.getCacheName() + "::" + request.getCacheKey()));

        return request;
    }
}
