package com.red.circle.other.infra.database.rds.service.user.user.impl;


import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.other.infra.database.rds.dao.user.user.ExpandDAO;
import com.red.circle.other.infra.database.rds.entity.user.user.UserExpand;
import com.red.circle.other.infra.database.rds.service.user.user.ExpandService;
import com.red.circle.other.inner.model.dto.user.ActiveUserCountryCodeDTO;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;


/**
 * <p>
 * 用户扩展信息 服务实现类
 * </p>
 *
 * @author pengliang
 * @since 2019-10-30
 */
@RequiredArgsConstructor
@Service
public class ExpandServiceImpl extends BaseServiceImpl<ExpandDAO, UserExpand> implements ExpandService {

  private Boolean exists(Long userId) {
    return Optional.ofNullable(
            query().select(UserExpand::getUserId).eq(UserExpand::getUserId, userId).last(PageConstant.LIMIT_ONE)
                .getOne()
        ).map(expand -> Objects.nonNull(expand.getUserId()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public void notExistsCreate(UserExpand userExpand) {
    if (!exists(userExpand.getUserId())) {
      save(userExpand);
    }
  }

  @Override
  public void init(Long userId, String language) {
    save(new UserExpand().setUserId(userId).setLanguage(language));
  }

  @Override
  public Locale getLanguage(Long userId) {
    return org.springframework.util.StringUtils.parseLocale(getLanguageStr(userId));
  }

  @Override
  public String getLanguageStr(Long userId) {
    return Optional.ofNullable(
            query().select(UserExpand::getLanguage)
                .eq(UserExpand::getUserId, userId)
                .last(PageConstant.LIMIT_ONE)
                .getOne())
        .map(UserExpand::getLanguage)
        .orElse(Locale.ENGLISH.getLanguage());
  }

  @Override
  public void updateLastActiveTime(Long userId) {
    update()
        .set(UserExpand::getLastActiveTime, LocalDateTime.now())
        .eq(UserExpand::getUserId, userId)
        .execute();
  }

  @Override
  public void updateLastActiveTimeAndLange(Long userId, String language) {
    update()
        .set(UserExpand::getLastActiveTime, LocalDateTime.now())
        .set(UserExpand::getLanguage, language)
        .eq(UserExpand::getUserId, userId)
        .execute();
  }

  @Override
  public Map<Long, UserExpand> mapExpand(Set<Long> userIds) {
    if (CollectionUtils.isEmpty(userIds)) {
      return CollectionUtils.newHashMap();
    }
    return Optional.ofNullable(query()
            .in(userIds.size() > 1, UserExpand::getUserId, userIds)
            .eq(Objects.equals(userIds.size(), 1), UserExpand::getUserId, userIds.iterator().next())
            .list())
        .map(expands -> expands.stream().collect(Collectors.toMap(UserExpand::getUserId, v -> v)))
        .orElse(CollectionUtils.newHashMap());
  }

  @Override
  public List<UserExpand> listUserExpand(Set<Long> userIds) {
    return query().in(UserExpand::getUserId, userIds).list();
  }

  @Override
  public Integer getUnlockArchiveSize(Long userId) {
    return Optional.ofNullable(query()
            .select(UserExpand::getUnlockArchiveSize)
            .eq(UserExpand::getUserId, userId)
            .last(PageConstant.LIMIT_ONE)
            .getOne())
        .map(UserExpand::getUnlockArchiveSize)
        .orElse(0);
  }

  @Override
  public void incrUnlockArchiveSize(Long userId) {
    update()
        .setSql("unlock_archive_size=unlock_archive_size+1")
        .eq(UserExpand::getUserId, userId)
        .execute();
  }

  @Override
  public void updatePurchasingToTrue(Long userId) {
    update().set(UserExpand::getPurchasing, Boolean.TRUE).eq(UserExpand::getUserId, userId).execute();
  }


  @Override
  public boolean checkPurchasing(Long userId) {
    return Optional.ofNullable(
            query().select(UserExpand::getPurchasing)
                .eq(UserExpand::getUserId, userId)
                .last(PageConstant.LIMIT_ONE)
                .getOne()
        ).map(expand -> Objects.equals(expand.getPurchasing(), Boolean.TRUE))
        .orElse(Boolean.FALSE);
  }

  @Override
  public Map<Long, String> mapUserLanguageStr(Set<Long> userIds) {
    return Optional.ofNullable(
            query().select(UserExpand::getUserId, UserExpand::getLanguage)
                .in(UserExpand::getUserId, userIds).list())
        .map(expands -> expands.stream()
            .collect(Collectors.toMap(UserExpand::getUserId, UserExpand::getLanguage)))
        .orElse(CollectionUtils.newHashMap());
  }

  @Override
  public List<ActiveUserCountryCodeDTO> findLatestActiveUserCountryCode(
      LocalDateTime lastActiveTime) {
    return findLatestActiveUserCountryCode(lastActiveTime);
  }


}
