package com.hdkj.lt.core.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.hdkj.lt.base.constants.RedisKeyConstants;
import com.hdkj.lt.base.constants.RoleConstants;
import com.hdkj.lt.base.constants.SymbolConstants;
import com.hdkj.lt.base.enums.YesOrNoEnum;
import com.hdkj.lt.core.sys.dao.SysUserMapper;
import com.hdkj.lt.core.sys.model.dto.UserQueryDTO;
import com.hdkj.lt.core.sys.model.po.SysUser;
import com.hdkj.lt.core.sys.service.ISysRolesService;
import com.hdkj.lt.core.sys.service.ISysStruService;
import com.hdkj.lt.core.sys.service.ISysUserRoleService;
import com.hdkj.lt.core.sys.service.ISysUserService;
import com.hdkj.lt.utils.cache.RedisRepository;
import com.hdkj.lt.core.sys.model.po.SysRoles;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: wenhao
 * @Create: 2024/02/20 10:08
 * @Version: 1.0
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    public static final String ATTRIBUTE_USER_ROLE_TYPE = "USER_ROLE_TYPE";

    private final RedisRepository redisRepository;

    private final ISysRolesService sysRolesService;

    private final ISysUserRoleService sysUserRoleService;

    private final ISysStruService sysStruService;

//    @Override
//    public void putAllToCache() {
//        redisRepository.del(RedisKeyConstants.CACHE_KEY_USERS_HASH);
//        Map<String, Object> dbMap = super.list(new LambdaQueryWrapper<SysUser>().eq(SysUser::getIsSys, YesOrNoEnum.NO.getCode()))
//                .stream().collect(Collectors.toMap(e -> String.valueOf(e.getUserId()), e -> e));
//        redisRepository.putHashValues(RedisKeyConstants.CACHE_KEY_USERS_HASH, dbMap);
//        dbMap.forEach((k, v) -> {
//            String key = RedisKeyConstants.CACHE_KEY_USERS_INDIES + SymbolConstants.COLON_EN + k;
//            HussarCacheUtil.evict(RedisKeyConstants.CACHE_KEY_USERS_INDIES, key);
//            HussarCacheUtil.put(RedisKeyConstants.CACHE_KEY_USERS_INDIES, key, v);
//        });
//    }

//    @Override
//    public SysUser getCacheOne(@Nonnull Long userId) {
//        String key = RedisKeyConstants.CACHE_KEY_USERS_INDIES + SymbolConstants.COLON_EN + userId;
//        SysUser sysUser = HussarCacheUtil.get(RedisKeyConstants.CACHE_KEY_USERS_INDIES, key);
//        if (Objects.isNull(sysUser) || StringUtils.isBlank(sysUser.getIscId())) {
//            sysUser = super.getById(userId);
//            HussarCacheUtil.put(RedisKeyConstants.CACHE_KEY_USERS_INDIES, key, sysUser);
//        }
//        return sysUser;
//    }

    @Override
    public void putAllToCache() {

    }

    @Override
    public SysUser getCacheOne(@Nonnull Long userId) {
        return null;
    }

    @Override
    public SysUser getCacheById(@Nonnull Long userId) {
        Map<String, Object> cacheMap = redisRepository.getHashValue(RedisKeyConstants.CACHE_KEY_USERS_HASH);
        SysUser sysUser = (SysUser) cacheMap.get(String.valueOf(userId));
        // ISC用户首次登录系统时会更新SYS_USERS.ISC_ID，而缓存中未及时更新，这里判断后进行更新
        if (Objects.isNull(sysUser) || StringUtils.isBlank(sysUser.getIscId())) {
            sysUser = super.getById(userId);
            cacheMap.put(String.valueOf(userId), sysUser);
            redisRepository.putHashValues(RedisKeyConstants.CACHE_KEY_USERS_HASH, cacheMap);
        }
        return sysUser;
    }

    @Override
    public Map<Long, SysUser> getCacheMapByIds(Collection<Long> userIds) {
        Map<Long, SysUser> resultMap = Maps.newHashMap();
        if (CollectionUtils.isEmpty(userIds)) {
            return resultMap;
        }
        Map<String, Object> cacheMap = redisRepository.getHashValue(RedisKeyConstants.CACHE_KEY_USERS_HASH);
        userIds = userIds.stream().distinct().collect(Collectors.toList());
        userIds.forEach(i -> Optional.ofNullable(cacheMap.get(String.valueOf(i))).ifPresent(e -> resultMap.put(i, (SysUser) e)));
        Set<Long> queriedIds = resultMap.keySet();
        if (CollectionUtils.size(userIds) != CollectionUtils.size(queriedIds)) {
            List<Long> notFoundIds = (List<Long>) CollectionUtils.removeAll(userIds, queriedIds);
            Map<Long, SysUser> dbMap = super.listByIds(notFoundIds).stream().collect(Collectors.toMap(SysUser::getUserId, e -> e));
            resultMap.putAll(dbMap);
            cacheMap.putAll(dbMap.entrySet().stream().collect(Collectors.toMap(e -> String.valueOf(e.getKey()), Map.Entry::getValue)));
            redisRepository.putHashValues(RedisKeyConstants.CACHE_KEY_USERS_HASH, cacheMap);
        }
        return resultMap;
    }

    @Override
    public Set<SysUser> getCacheSetByIds(Collection<Long> userIds) {
        Set<SysUser> resultSet = Sets.newHashSet();
        if (CollectionUtils.isEmpty(userIds)) {
            return resultSet;
        }
        Map<String, Object> cacheMap = redisRepository.getHashValue(RedisKeyConstants.CACHE_KEY_USERS_HASH);
        userIds = userIds.stream().distinct().collect(Collectors.toList());
        userIds.forEach(i -> Optional.ofNullable(cacheMap.get(String.valueOf(i))).ifPresent(e -> resultSet.add((SysUser) e)));
        List<Long> queriedIds = resultSet.stream().map(SysUser::getUserId).collect(Collectors.toList());
        if (CollectionUtils.size(userIds) != CollectionUtils.size(queriedIds)) {
            List<Long> notFoundIds = (List<Long>) CollectionUtils.removeAll(userIds, queriedIds);
            List<SysUser> dbList = super.listByIds(notFoundIds);
            resultSet.addAll(dbList);
            Map<Long, SysUser> dbMap = dbList.stream().collect(Collectors.toMap(SysUser::getUserId, e -> e));
            cacheMap.putAll(dbMap.entrySet().stream().collect(Collectors.toMap(e -> String.valueOf(e.getKey()), Map.Entry::getValue)));
            redisRepository.putHashValues(RedisKeyConstants.CACHE_KEY_USERS_HASH, cacheMap);
        }
        return resultSet;
    }

//    @Override
//    public Set<SysRoles> getRoles(Long userId) {
//        if (Objects.isNull(userId)) {
//            SecurityUser user = SecurityUtils.getUser();
//            return sysRolesService.getCacheSetByIds(user.getRolesList());
//        }
//        List<Long> roleIds = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId)).stream().map(SysUserRole::getGrantedRole).collect(Collectors.toList());
//        return sysRolesService.getCacheSetByIds(roleIds);
//    }


    @Override
    public Set<SysRoles> getRoles(@Nullable Long userId) {
        return Collections.emptySet();
    }

    @Override
    public List<SysUser> listByCondition(UserQueryDTO queryDTO) {
        return this.baseMapper.listByCondition(queryDTO);
    }

}
