package cokr.xit.ens.modules.common.ctgy.sys.mng.service.strategy;

import cokr.xit.ens.core.config.redis.CacheKey;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.TmpltMngRepositorySupport;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.time.Duration;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@RequiredArgsConstructor
public abstract class TmpltMngCacheSupport<D> {

    protected final String KEY = CacheKey.TMPLTMNG;
    protected final Long KEY_EXPIRE = CacheKey.TMPLTMNG_EXP_SEC;


    /**
     * 템플릿 캐시 저장
     *
     * @param redisTemplate
     * @param orgCd
     * @param tmpltCd
     * @param tmpltMngRepositorySupport
     * @return
     */
    protected String pushCache(RedisTemplate redisTemplate, String orgCd, String tmpltCd, TmpltMngRepositorySupport tmpltMngRepositorySupport) {
        final String hk = orgCd + ":" + tmpltCd + ":" + this.getClass().getSimpleName();
        HashOperations<String, String, D> hashOperations = redisTemplate.opsForHash();
        if (redisTemplate.hasKey(KEY)) {
            if (!hashOperations.entries(KEY).containsKey(hk)) {
                Optional<D> tmpltMngDTOByStrategy = tmpltMngRepositorySupport.findDtoByOrgCdAndTmpltCd(orgCd, tmpltCd);
                if (tmpltMngDTOByStrategy.isPresent()) {
                    hashOperations.put(KEY, hk, tmpltMngDTOByStrategy.get());
                }
            }
        } else {
            Optional<D> tmpltMngDTO = tmpltMngRepositorySupport.findDtoByOrgCdAndTmpltCd(orgCd, tmpltCd);
            if (tmpltMngDTO.isPresent()) {
                hashOperations.put(KEY, hk, tmpltMngDTO.get());
                hashOperations.getOperations().expire(KEY, Duration.ofSeconds(KEY_EXPIRE));
            }
        }

        return hk;
    }


    /**
     * ID(orgCd, tmpltCd)가 일치하는 모든 템플릿 캐시 삭제
     *
     * @param redisTemplate
     * @param orgCd
     * @param tmpltCd
     */
    protected void deleteCache(RedisTemplate redisTemplate, String orgCd, String tmpltCd) {
        HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
        if (redisTemplate.hasKey(KEY)) {
            Map<String, Object> m = hashOperations.entries(KEY);
            m.keySet().stream()
                    .filter(key -> key.startsWith(orgCd + ":" + tmpltCd + ":"))
                    .collect(Collectors.toList())
                    .forEach(hk -> m.remove(hk));
            hashOperations.putAll(KEY, m);
        }
    }


}
