package com.red.circle.other.infra.database.cache.service.other.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.other.infra.database.cache.entity.dynamic.DynamicTagConfigCache;
import com.red.circle.other.infra.database.cache.entity.dynamic.TopDynamicCache;
import com.red.circle.other.infra.database.cache.key.DynamicKeys;
import com.red.circle.other.infra.database.cache.service.other.DynamicCacheService;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.DateFormatConstant;
import com.red.circle.tool.core.date.LocalDateTimeUtils;
import com.red.circle.tool.core.func.VoidCallable;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 动态
 *
 * @author pengliang
 * @since 2022/4/12
 */
@Service
@RequiredArgsConstructor
public class DynamicCacheServiceImpl implements DynamicCacheService {

  private final RedisService redisService;

  @Override
  public List<DynamicTagConfigCache> getCaches(SysOriginPlatformEnum sysOrigin, String language,
      VoidCallable<List<DynamicTagConfigCache>> orElse) {

    List<DynamicTagConfigCache> tagConfigCaches = redisService.hashGet(
        DynamicKeys.DYNAMIC_TAG.name(), getDynamicTagKey(sysOrigin, language),
        new TypeReference<>() {
        });

    if (CollectionUtils.isNotEmpty(tagConfigCaches)) {
      return tagConfigCaches;
    }
    List<DynamicTagConfigCache> newTagConfigCaches = orElse.apply();
    if (CollectionUtils.isNotEmpty(newTagConfigCaches)) {
      redisService.hashPut(DynamicKeys.DYNAMIC_TAG.name(),
          getDynamicTagKey(sysOrigin, language), newTagConfigCaches);
    }
    return newTagConfigCaches;
  }

  private String getDynamicTagKey(SysOriginPlatformEnum sysOrigin, String language) {
    return sysOrigin.concatUnderscoreJoin(DynamicKeys.DYNAMIC_TAG.name() + "_" + language);
  }

  @Override
  public void remove() {
    redisService.delete(DynamicKeys.DYNAMIC_TAG.name());
  }

  /**
   * 评论数量key
   */
  private String getCommentQuantityKey(Long dynamicContentId) {
    return DynamicKeys.DYNAMIC_COMMENT_QUANTITY.getKey(dynamicContentId);
  }

  @Override
  public Long updateCommentQuantity(Long dynamicContentId, Integer quantity) {

    return redisService.increment(getCommentQuantityKey(dynamicContentId), quantity, 30,
        TimeUnit.DAYS);

  }

  @Override
  public Integer initCommentQuantity(Long dynamicContentId, Integer quantity) {
    redisService
        .setString(getCommentQuantityKey(dynamicContentId), quantity, 30, TimeUnit.DAYS);
    return quantity;
  }

  @Override
  public Integer getCommentQuantity(Long dynamicContentId) {
    return redisService.getStringToInteger(getCommentQuantityKey(dynamicContentId));
  }

  /**
   * 动态点赞数量key
   */
  private String getLikeQuantityKey(Long dynamicContentId) {
    return DynamicKeys.DYNAMIC_LIKE_QUANTITY.getKey(dynamicContentId);
  }

  @Override
  public Long incrLikeQuantity(Long dynamicContentId) {
    return redisService
        .increment(getLikeQuantityKey(dynamicContentId), 1, 30, TimeUnit.DAYS);
  }

  @Override
  public Long decrLikeQuantity(Long dynamicContentId) {
    Long quantity = getLikeQuantity(dynamicContentId);
    if (Objects.isNull(quantity) || quantity <= 0) {
      redisService.delete(getLikeQuantityKey(dynamicContentId));
      return 0L;
    }
    return redisService.decrement(getLikeQuantityKey(dynamicContentId), 1);
  }

  @Override
  public void initLikeQuantity(Long dynamicContentId, Long quantity) {
    redisService
        .setString(getLikeQuantityKey(dynamicContentId), quantity, 30, TimeUnit.DAYS);
  }

  @Override
  public Long getLikeQuantity(Long dynamicContentId) {
    return redisService.getStringToLong(getLikeQuantityKey(dynamicContentId));
  }

  /**
   * 动态点赞数量key
   */
  private String getCommentLikeQuantityKey(Long dynamicContentId, Long commentId) {
    return DynamicKeys.DYNAMIC_LIKE_COMMENT_QUANTITY
        .getKey(dynamicContentId + "_" + commentId);
  }

  @Override
  public Long incrCommentLikeQuantity(Long dynamicContentId, Long commentId) {
    return redisService.increment(getCommentLikeQuantityKey(dynamicContentId, commentId), 1, 30,
        TimeUnit.DAYS);
  }

  @Override
  public Long decrCommentLikeQuantity(Long dynamicContentId, Long commentId) {

    Long quantity = getCommentLikeQuantity(dynamicContentId, commentId);
    if (Objects.isNull(quantity) || quantity <= 0) {
      redisService.delete(getCommentLikeQuantityKey(dynamicContentId, commentId));
      return 0L;
    }

    return redisService.decrement(getCommentLikeQuantityKey(dynamicContentId, commentId), 1);
  }

  @Override
  public void initCommentLikeQuantity(Long dynamicContentId, Long commentId, Long quantity) {
    redisService
        .setString(getCommentLikeQuantityKey(dynamicContentId, commentId), quantity, 30,
            TimeUnit.DAYS);
  }

  @Override
  public Long getCommentLikeQuantity(Long dynamicContentId, Long commentId) {
    return Optional.ofNullable(redisService
        .getStringToLong(getCommentLikeQuantityKey(dynamicContentId, commentId))).orElse(0L);
  }

  @Override
  public void pushLikeScore(Integer score) {
    if (Objects.isNull(score) || score <= 0) {
      score = 0;
    }
    redisService.setString(DynamicKeys.DYNAMIC_LIKE_WEIGHTS_SCORE.name(), score);
  }

  @Override
  public Integer getLikeScore() {
    return Optional.ofNullable(
            redisService.getStringToInteger(DynamicKeys.DYNAMIC_LIKE_WEIGHTS_SCORE.name()))
        .orElse(0);
  }

  @Override
  public void pushCommentScore(Integer score) {
    if (Objects.isNull(score) || score <= 0) {
      score = 0;
    }
    redisService.setString(DynamicKeys.DYNAMIC_COMMENT_WEIGHTS_SCORE.name(), score);
  }

  @Override
  public Integer getCommentScore() {
    return Optional.ofNullable(
            redisService.getStringToInteger(DynamicKeys.DYNAMIC_COMMENT_WEIGHTS_SCORE.name()))
        .orElse(0);
  }

  @Override
  public void pushSendLevelLimit(Long levelLimit) {
    redisService.setString(DynamicKeys.DYNAMIC_SEND_LEVEL_LIMIT.name(), levelLimit);
  }

  @Override
  public Long getSendLevelLimit() {
    return Optional.ofNullable(redisService
        .getStringToLong(DynamicKeys.DYNAMIC_SEND_LEVEL_LIMIT.name())).orElse(0L);
  }

  @Override
  public void pushSendQuantityLimit(Long quantityLimit) {
    redisService
        .setString(DynamicKeys.DYNAMIC_SEND_QUANTITY_LIMIT.name(), quantityLimit);
  }

  @Override
  public Long getSendQuantityLimit() {
    return Optional.ofNullable(redisService
        .getStringToLong(DynamicKeys.DYNAMIC_SEND_QUANTITY_LIMIT.name())).orElse(0L);
  }

  @Override
  public void pushSendDynamicFees(Long dynamicFees) {
    redisService.setString(DynamicKeys.DYNAMIC_SEND_FEES.name(), dynamicFees);
  }

  @Override
  public Long getSendDynamicFees() {
    return Optional.ofNullable(redisService
        .getStringToLong(DynamicKeys.DYNAMIC_SEND_FEES.name())).orElse(0L);
  }

  @Override
  public Long getUserTodayDynamicCount(Long userId) {
    return Optional
        .ofNullable(
            redisService.getStringToLong(getUserTodayDynamicCountAppendKey(userId)))
        .orElse(0L);
  }

  @Override
  public Long incrUserTodayDynamicCount(Long userId) {
    return redisService
        .increment(getUserTodayDynamicCountAppendKey(userId), 1, TimeUnit.DAYS);
  }

  private String getUserTodayDynamicCountAppendKey(Long userId) {
    return DynamicKeys.DYNAMIC_USER_SEND_COUNT.getKey(
        LocalDateTimeUtils.nowFormat(DateFormatConstant.yyyyMMdd) + "_" + userId);
  }

  @Override
  public void removeTopDynamic() {
    redisService.delete(DynamicKeys.DYNAMIC_TOP.name());
  }

  @Override
  public List<TopDynamicCache> getTopDynamicCache(SysOriginPlatformEnum sysOrigin,
      VoidCallable<List<TopDynamicCache>> orElse) {

    List<TopDynamicCache> caches = redisService.hashGet(DynamicKeys.DYNAMIC_TOP.name(),
        getTopDynamicKey(sysOrigin), new TypeReference<>() {
        });

    if (CollectionUtils.isNotEmpty(caches)) {
      return caches;
    }
    List<TopDynamicCache> newCaches = orElse.apply();
    if (CollectionUtils.isNotEmpty(newCaches)) {
      redisService.hashPut(DynamicKeys.DYNAMIC_TOP.name(),
          getTopDynamicKey(sysOrigin), newCaches);
    }
    return newCaches;
  }

  private String getTopDynamicKey(SysOriginPlatformEnum sysOrigin) {
    return sysOrigin.concatUnderscoreJoin(DynamicKeys.DYNAMIC_TOP.name());
  }

  @Override
  public void cachePendingDynamicIds(List<Long> dynamicIds) {
    if (CollectionUtils.isEmpty(dynamicIds)) {
      redisService.delete(DynamicKeys.DYNAMIC_PENDING_IDS.name());
      return;
    }
    redisService.setString(DynamicKeys.DYNAMIC_PENDING_IDS.name(), dynamicIds, 1, TimeUnit.HOURS);
  }

  @Override
  public List<Long> getPendingDynamicIds() {
    return Optional.ofNullable(
        redisService.getStringToObject(DynamicKeys.DYNAMIC_PENDING_IDS.name(), new TypeReference<List<Long>>() {})
    ).orElse(CollectionUtils.newArrayList());
  }

  @Override
  public void clearPendingDynamicIds() {
    redisService.delete(DynamicKeys.DYNAMIC_PENDING_IDS.name());
  }

}
