package cn.quantgroup.xyqb.service.user.impl;

import cn.quantgroup.tech.db.DSType;
import cn.quantgroup.tech.db.TargetDataSource;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.UserAttached;
import cn.quantgroup.xyqb.repository.IUserAttachedRepository;
import cn.quantgroup.xyqb.repository.IUserRepository;
import cn.quantgroup.xyqb.service.user.ITenantService;
import cn.quantgroup.xyqb.service.user.UserCenterService;
import cn.quantgroup.xyqb.util.EmojiUtil;
import cn.quantgroup.xyqb.util.TenantUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Created by 11 on 2017/3/22.
 */
@Slf4j
@Service
public class UserCenterServiceImpl implements UserCenterService {

    @Autowired
    private IUserAttachedRepository userAttachedRepository;

    @Autowired
    private IUserRepository userRepository;

    @Autowired
    private ITenantService tenantService;

    @Override
    @TargetDataSource(type = DSType.SLAVE)//查询从库
//    @Cacheable(value = "userAttachedCache", key = "'xyqbUserAttached' + #userId", unless = "#result == null", cacheManager = "cacheManager")
    public UserAttached searchUserAttachedByUserId(long userId) {
        return userAttachedRepository.findByUserId(userId);
    } 

    @Override
    public List<UserAttached> searchUserAttachedListByUserId(List<Long> userIds, Integer tenantId) {
        List<UserAttached> resultProductUsers = new ArrayList<>();
        List<UserAttached> userAttacheds = userAttachedRepository.findByUserIdIn(userIds);
        if (!tenantId.equals(TenantUtil.TENANT_DEFAULT)) {
            if (userAttacheds != null) {
                //租户ID校验
                if (!TenantUtil.validationTenantIdIsNullOrZero(tenantId)) {
                    List<User> users = userRepository.findByIdIn(userIds);
                    List<User> productUsers = tenantService.selectUsersByTenantId(users, tenantId);
                    if (productUsers != null) {
                        List<Long> collect = productUsers.stream().map(User::getId).collect(Collectors.toList());
                        userAttacheds.forEach(a->{
                            if (collect.contains(a.getUserId())) {
                                resultProductUsers.add(a);
                            }
                        });
                    }
                    return resultProductUsers;
                }
            }
        }else {
            List<User> users = userRepository.findByIdIn(userIds);
            List<User> productUsers = tenantService.validationTentIdByTentId(users, tenantId);
            if (productUsers != null) {
                List<Long> collect = productUsers.stream().map(User::getId).collect(Collectors.toList());
                userAttacheds.forEach(a->{
                    if (collect.contains(a.getUserId())) {
                        resultProductUsers.add(a);
                    }
                });
            }
        }
        return resultProductUsers;
    }

    @Override
    @CacheEvict(value = "userAttachedCache", key = "'xyqbUserAttached' + #userId", cacheManager = "cacheManager")
    public UserAttached saveUserAvatar(long userId, String avatar) {
        UserAttached userAttached = userAttachedRepository.findByUserId(userId);
        if(Objects.isNull(userAttached)){
            userAttached = createUserAttached(userId, avatar, null);
        }
        if(!Objects.equals(avatar, userAttached.getAvatar())){
            userAttached.setAvatar(avatar);
            userAttached = userAttachedRepository.save(userAttached);
        }
        return userAttached;
    }

    @Override
    @CacheEvict(value = "userAttachedCache", key = "'xyqbUserAttached' + #userId", cacheManager = "cacheManager")
    public UserAttached saveUserNick(long userId, String nick) {
        UserAttached userAttached = userAttachedRepository.findByUserId(userId);
        // 替换所有,UTF-8编码时4字节的Emoji表情字符
        nick = EmojiUtil.filterUnicode4(nick);
        if(Objects.isNull(userAttached)){
            userAttached = createUserAttached(userId, null, nick);
        }
        if(!Objects.equals(nick, userAttached.getNick())){
            userAttached.setNick(nick);
            try {
                userAttached = userAttachedRepository.save(userAttached);
            }catch (ConstraintViolationException e){
                // Sql唯一约束异常（诱因是Form重复提交，因为该操作是幂等的，故此不需额外处理，可返回成功）
                log.error("Sql约束异常[uni_idx_user_id]重复提交Form是幂等操作，不影响处理结果", e);
            }
        }
        return userAttached;
    }

    /**
     * 创建用户附加信息实体
     *
     * @param userId - 用户主键
     * @param avatar - 头像url地址
     * @param nick - 昵称
     * @return
     */
    private synchronized UserAttached createUserAttached(Long userId, String avatar, String nick) {
        UserAttached userAttached = userAttachedRepository.findByUserId(userId);
        // 更新实例
        userAttached = Optional.ofNullable(userAttached).orElse(new UserAttached());
        userAttached.setUserId(userId);
        if(StringUtils.isBlank(userAttached.getAvatar())){
            userAttached.setAvatar(avatar);
        }
        if(StringUtils.isBlank(userAttached.getNick())){
            userAttached.setNick(nick);
        }
        return userAttachedRepository.save(userAttached);
    }
}
