package com.red.circle.other.infra.annotation.aspect;

import com.google.common.collect.Lists;
import com.red.circle.framework.web.spring.SpElParse;
import com.red.circle.other.infra.annotation.RemoveUserActionCache;
import com.red.circle.other.infra.database.cache.key.user.UserHashKey;
import com.red.circle.other.infra.database.cache.service.user.UserCacheService;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.json.JacksonUtils;
import com.red.circle.tool.core.parse.DataTypeUtils;
import com.red.circle.tool.core.regex.RegexConstant;
import com.red.circle.tool.core.text.StringPool;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

/**
 * 清空我的基本信息缓存.
 *
 * @author pengliang on 2019/11/27 16:56
 */
@Aspect
@Slf4j
@Component
@RequiredArgsConstructor
public class RemoveUserActionCacheAspect extends SpElParse {

  private final UserCacheService userCacheService;

  @Pointcut("@annotation(com.red.circle.other.infra.annotation.RemoveUserActionCache)")
  public void removeUserActionCache() {
  }

  @After("removeUserActionCache()")
  public void removeUserCache(JoinPoint joinPoint) {
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    RemoveUserActionCache removeUserActionCache = signature.getMethod()
        .getAnnotation(RemoveUserActionCache.class);
    List<Long> userIds = getUserIds(removeUserActionCache.value(), joinPoint);
    if (CollectionUtils.isEmpty(userIds)) {
      log.error("removeUserCache not parse userId:{}",
          JacksonUtils.toJson(removeUserActionCache.value()));
      return;
    }
    UserHashKey[] keys = removeUserActionCache.hashKey();
    if (keys.length > 0) {
      userIds.forEach(userId -> userCacheService.remove(userId, keys));
      return;
    }
    userCacheService.remove(userIds);
  }

  public List<Long> getUserIds(String[] userIds, JoinPoint joinPoint) {
    if (Objects.isNull(userIds) || userIds.length == 0) {
      return null;
    }
    List<Long> ids = Lists.newArrayList();
    for (String userId : userIds) {
      if (userId.startsWith(StringPool.WELL_NUMBER)) {
        Object objValue = parse(userId, joinPoint);
        if (objValue instanceof List) {
          @SuppressWarnings("unchecked")
          List<Object> list = (List<Object>) objValue;
          ids.addAll(list.stream().filter(uid -> uid instanceof Long || uid instanceof String)
              .map(DataTypeUtils::toLong)
              .collect(Collectors.toList()));
          continue;
        }
        ids.add(DataTypeUtils.toLong(objValue));
        continue;
      }

      if (userId.matches(RegexConstant.NUMBER)) {
        ids.add(Long.valueOf(userId));
      }
    }
    return ids.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
  }
}
