
package com.tmerclub.cloud.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.cache.constant.UserCacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.constant.StatusEnum;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.user.constant.LevelTypeEnum;
import com.tmerclub.cloud.user.dto.UserRightsDTO;
import com.tmerclub.cloud.user.mapper.UserLevelMapper;
import com.tmerclub.cloud.user.mapper.UserLevelRightsMapper;
import com.tmerclub.cloud.user.mapper.UserRightsCouponMapper;
import com.tmerclub.cloud.user.mapper.UserRightsMapper;
import com.tmerclub.cloud.user.model.UserLevel;
import com.tmerclub.cloud.user.model.UserRights;
import com.tmerclub.cloud.user.model.UserRightsCoupon;
import com.tmerclub.cloud.user.service.UserLevelRightsService;
import com.tmerclub.cloud.user.service.UserRightsService;
import com.tmerclub.cloud.user.vo.UserRightsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 用户权益信息
 *
 * @author YXF
 * @date 2020-12-08 10:16:53
 */
@Service
public class UserRightsServiceImpl implements UserRightsService {

    @Autowired
    private UserRightsMapper userRightsMapper;

    @Autowired
    private UserRightsCouponMapper userRightsCouponMapper;

    @Autowired
    private UserLevelRightsMapper userLevelRightsMapper;

    @Autowired
    private UserLevelMapper userLevelMapper;


    @Autowired
    private UserLevelRightsService userLevelRightsService;


    @Override
    public PageVO<UserRightsVO> page(PageDTO pageDTO, UserRightsDTO userRightsDTO) {
        return PageUtil.doPage(pageDTO, () -> userRightsMapper.list(userRightsDTO));
    }

    @Override
    @Cacheable(cacheNames = CacheNames.RIGHT_BY_RIGHTS_ID_KEY, key = "#rightsId")
    public UserRightsVO getByRightsId(Long rightsId) {
        return userRightsMapper.getByRightsId(rightsId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(UserRightsDTO userRightsDTO) {
        //  checkIsRepeat(userRightsDTO);
        UserRights userRights = BeanUtil.map(userRightsDTO, UserRights.class);
        userRights.setStatus(StatusEnum.ENABLE.value());
        userRightsMapper.save(userRights);
        userRightsDTO.setRightsId(userRights.getRightsId());
        Long rightsId = userRights.getRightsId();
        List<Long> couponIds = userRightsDTO.getCouponIds();
        for (Long couponId : couponIds) {
            UserRightsCoupon userRightsCoupon = new UserRightsCoupon();
            userRightsCoupon.setCouponId(couponId);
            userRightsCoupon.setRightsId(rightsId);
            userRightsCouponMapper.save(userRightsCoupon);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(UserRightsDTO userRightsDTO) {
        //  checkIsRepeat(userRightsDTO);
        UserRights userRights = BeanUtil.map(userRightsDTO, UserRights.class);
        userRights.setStatus(StatusEnum.ENABLE.value());
        Long rightsId = userRights.getRightsId();
        userRightsCouponMapper.deleteByRightsId(rightsId);
        List<Long> couponIds = userRightsDTO.getCouponIds();
        for (Long couponId : couponIds) {
            UserRightsCoupon userRightsCoupon = new UserRightsCoupon();
            userRightsCoupon.setCouponId(couponId);
            userRightsCoupon.setRightsId(rightsId);
            userRightsCouponMapper.save(userRightsCoupon);
        }
        userRightsMapper.update(userRights);
        //删除有该权益的所有等级的权益列表缓存
        List<UserLevel> userLevelList = userLevelRightsService.listUserLevelIdByRightId(userRightsDTO.getRightsId());
        removeLevelCache(userLevelList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Long rightsId) {
        //删除有该权益的所有等级的权益列表缓存
        List<UserLevel> userLevelList = userLevelRightsService.listUserLevelIdByRightId(rightsId);
        userRightsCouponMapper.deleteByRightsId(rightsId);
        userRightsMapper.deleteById(rightsId);
        userLevelRightsMapper.deleteByRightId(rightsId);
        removeLevelCache(userLevelList);
    }

    @Override
    public List<UserRightsVO> list(UserRightsDTO userRights) {
        return userRightsMapper.list(userRights);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.RIGHT_BY_RIGHTS_ID_KEY, key = "#rightsId")
    public void removeRightsCache(Long rightsId) {

    }

    @Override
    public void removeRightsByLevelTypeCache(Integer levelType) {
        List<String> keys = new ArrayList<>(Constant.INITIAL_CAPACITY);
        setRightKeys(keys);
        RedisUtil.deleteBatch(keys);
    }

    private static void setRightKeys(List<String> keys) {
        int maxLevel = 4;
        for (int i = 1; i <= maxLevel; i++) {
            keys.add(CacheNames.RIGHTS_BY_LEVEL_TYPE + CacheNames.UNION + LevelTypeEnum.ORDINARY_USER.value() + CacheNames.UNION_KEY + i);
            keys.add(CacheNames.RIGHTS_BY_LEVEL_TYPE + CacheNames.UNION + LevelTypeEnum.PAY_USER.value() + CacheNames.UNION_KEY + i);
        }
    }

    @Override
    @Cacheable(cacheNames = CacheNames.RIGHTS_BY_LEVEL_TYPE, key = "#levelType +':'+ #nowLevel")
    public List<UserRightsVO> listRightsByLevelType(Integer levelType, Integer nowLevel) {
        List<UserRightsVO> total = userRightsMapper.listRightsByLevelType(levelType);
        // set存放处理过的rightsType
        Set<Integer> haveReadType = new HashSet<>(Constant.INITIAL_CAPACITY);
        Set<String> haveReadName = new HashSet<>(Constant.INITIAL_CAPACITY);
        //会员等级为key，权益内容为value
        Map<Integer, List<UserRightsVO>> res = new HashMap<>(total.size());
        for (UserRightsVO userRightsVO : total) {
            //非自定义权益根据类型去重
            if (Objects.equals(userRightsVO.getLevel(), nowLevel)) {
                if (!Objects.isNull(userRightsVO.getRightsType()) && userRightsVO.getRightsType() != 0) {
                    if (haveReadType.contains(userRightsVO.getRightsType())) {
                        continue;
                    }
                    Integer level = userRightsVO.getLevel();
                    List<UserRightsVO> list = res.getOrDefault(level, new ArrayList<>(Constant.INITIAL_CAPACITY));
                    list.add(userRightsVO);
                    res.put(level, list);
                    haveReadType.add(userRightsVO.getRightsType());
                } else {
                    //自定义类型根据名称去重
                    if (haveReadName.contains(userRightsVO.getRightsName())) {
                        continue;
                    }
                    Integer level = userRightsVO.getLevel();
                    List<UserRightsVO> list = res.getOrDefault(level, new ArrayList<>(Constant.INITIAL_CAPACITY));
                    list.add(userRightsVO);
                    res.put(level, list);
                    haveReadName.add(userRightsVO.getRightsName());
                }
            }
        }
        Set<Map.Entry<Integer, List<UserRightsVO>>> entries = res.entrySet();
        List<UserRightsVO> returnResult = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (Map.Entry<Integer, List<UserRightsVO>> entry : entries) {
            List<UserRightsVO> value = entry.getValue();
            returnResult.addAll(value);
        }
        return returnResult;
    }

    @Override
    public void cancelBindingCoupons(List<Long> couponIds) {
        List<Long> rightsIds = userRightsCouponMapper.listRightsIdByCouponIds(couponIds);
        // 没有要移除过期优惠券的权益
        if (CollUtil.isEmpty(rightsIds)) {
            return;
        }
        // 移除权益中过期的优惠券
        userRightsCouponMapper.deleteByCouponIds(couponIds);
        List<String> keys = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 清除权益缓存
        for (Long rightsId : rightsIds) {
            keys.add(CacheNames.RIGHT_BY_RIGHTS_ID_KEY + CacheNames.UNION + rightsId);
        }
        setRightKeys(keys);

        // 清除等级缓存
        List<UserLevel> userLevels = userLevelMapper.listByCouponIds(rightsIds);
        if (CollUtil.isNotEmpty(userLevels)) {
            for (UserLevel userLevel : userLevels) {
                keys.add(CacheNames.LEVEL_GET_KEY + CacheNames.UNION + userLevel.getUserLevelId());
                keys.add(CacheNames.LEVEL_GET_LIST_KEY + CacheNames.UNION + userLevel.getLevelType() + Constant.CATEGORY_INTERVAL + userLevel.getLevel());
            }
            keys.add(CacheNames.LEVEL_LIST_KEY + CacheNames.UNION + LevelTypeEnum.ORDINARY_USER.value());
            keys.add(CacheNames.LEVEL_LIST_KEY + CacheNames.UNION + LevelTypeEnum.PAY_USER.value());
        }
        RedisUtil.deleteBatch(keys);

    }

    @Override
    public List<UserRightsVO> listRightByLevel(Integer level, Integer levelType) {
        return userRightsMapper.listRightByLevel(level, levelType);
    }

    private void removeLevelCache(List<UserLevel> userLevelList) {
        List<String> keys = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (UserLevel userLevel : userLevelList) {
            keys.add(UserCacheNames.LEVEL_GET_KEY + CacheNames.UNION + userLevel.getUserLevelId());
            keys.add(UserCacheNames.LEVEL_GET_LIST_KEY + CacheNames.UNION + userLevel.getLevelType() + '-' + userLevel.getLevel());
        }
        keys.add(UserCacheNames.LEVEL_LIST_KEY + CacheNames.UNION + LevelTypeEnum.ORDINARY_USER.value());
        keys.add(UserCacheNames.LEVEL_LIST_KEY + CacheNames.UNION + LevelTypeEnum.PAY_USER.value());
        RedisUtil.del(keys);
    }

}
