package org.springblade.modules.guosen.rank.service;

import cn.hutool.core.collection.CollUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.modules.guosen.loginUser.entity.LoginUser;
import org.springblade.modules.guosen.loginUser.service.ILoginUserService;
import org.springblade.modules.guosen.loginUser.vo.LoginWebVO;
import org.springblade.modules.guosen.production.entity.Production;
import org.springblade.modules.guosen.production.service.IProductionService;
import org.springblade.modules.guosen.userActivityStatistical.entity.UserActivityStatistical;
import org.springblade.modules.guosen.userActivityStatistical.service.IUserActivityStatisticalService;
import org.springblade.modules.guosen.userActivityStatistical.vo.UserActivityStatisticalVO;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RankService{

	//选手排行榜，以活动分组
	private static final String KEY_USER= "user:";
	private static final String VALUE_USER= "userId:";

	//作品排行榜，以活动分组
	private static final String KEY_PRODUCTION= "production:";
	private static final String VALUE_PRODUCTION= "productionId:";


	@Resource
    private RedisService redisService;

	@Resource @Lazy
	private ILoginUserService loginUserService;
	@Resource @Lazy
	private IUserActivityStatisticalService userActivityStatisticalService;
	@Resource
	private IProductionService productionService;

    public void rankAddUser() {
		redisService.deleteObscure(KEY_USER);
		List<UserActivityStatistical> selectPlayerList = userActivityStatisticalService.selectPlayerList();
		if (CollUtil.isEmpty(selectPlayerList)) {
			return;
		}
		Map<Long, List<UserActivityStatistical>> listMaps = selectPlayerList.stream()
			.collect(Collectors.groupingBy(UserActivityStatistical::getActivityId));
		for (Long activityId : listMaps.keySet()) {
//			redisService.remove((KEY_USER+ activityId));
			List<UserActivityStatistical> statistical = listMaps.get(activityId);
			statistical.forEach(item->{
				redisService.zAdd((KEY_USER+ activityId), VALUE_USER+item.getUserId(), Double.parseDouble(item.getTotalHotValue().toString()));
			});
		}
    }

	public void rankAddProduction() {
		redisService.deleteObscure(KEY_PRODUCTION);
		List<Production> productions = productionService.list();
		if (CollUtil.isEmpty(productions)) {
			return;
		}
		Map<Long, List<Production>> listMaps = productions.stream().collect(Collectors.groupingBy(Production::getActivityId));
		for (Long activityId : listMaps.keySet()) {
//			redisService.remove((KEY_PRODUCTION+ activityId));
			List<Production> productionList = listMaps.get(activityId);
			productionList.forEach(item->{
				redisService.zAdd((KEY_PRODUCTION+ activityId), VALUE_PRODUCTION+item.getId(), Double.parseDouble(item.getHotValue().toString()));
			});
		}
	}

	/**
	 * 添加选手分数
	 * @param activityId 活动id
	 * @param valueId 用户id
	 * @param score 添加的分数
	 * @param type 0选手排行，1作品排行
	 */
    public void addScore(String activityId,String valueId,Double score,Integer type) {
		String keyName = "";
		String valueName = "";
		if (type==0) {
			keyName = KEY_USER;
			valueName = VALUE_USER;
		} else if (type == 1) {
			keyName = KEY_PRODUCTION;
			valueName = VALUE_PRODUCTION;
		}
		redisService.incrementScore(keyName + activityId, valueName + valueId, score);

	}
	/**
	 * 获取总数
	 * @param activityId 活动id
	 * @param type 查看的类型 0 选手 1 作品
	 * @return
	 */
	public Long getCount(String activityId, Integer type) {
		String keyName = "";
		if (type==0) {
			keyName = KEY_USER;
		} else if (type == 1) {
			keyName = KEY_PRODUCTION;
		}
		return redisService.getCount(keyName + activityId);
	}

	/**
	 * 查看选手的排名
	 * @return
	 */
    public LoginWebVO rank(String activityId,String valueId,Integer type) {
		String keyName = "";
		String valueName = "";
		Long userId = null;
		if (type == 0) {
			keyName = KEY_USER;
			valueName = VALUE_USER;
			userId = Long.valueOf(valueId);
		} else if (type == 1) {
			keyName = KEY_PRODUCTION;
			valueName = VALUE_PRODUCTION;
			userId = productionService.getById(Long.valueOf(valueId)).getUserId();;
		}
		Long rankLong = redisService.zRank((keyName + activityId), valueName + valueId);
		Double scoreDouble = redisService.zSetScore((keyName + activityId), valueName + valueId);
		if (rankLong == null || scoreDouble == null) {
			return null;
		}
		Integer rank=rankLong.intValue() + 1;
		String score = scoreDouble.toString();
//		try {
//			rank = redisService.zRank((keyName+activityId), valueName+valueId).intValue() + 1;
//			score = redisService.zSetScore((keyName+activityId), valueName+valueId).toString();
//		} catch (Exception e) {
//			if (type == 0) {
//				this.rankAddUser();
//			} else {
//				this.rankAddProduction();
//			}
//			rank = redisService.zRank((keyName+activityId), valueName+valueId).intValue() + 1;
//			score = redisService.zSetScore((keyName+activityId), valueName+valueId).toString();
//		}
		LoginUser loginUser = loginUserService.getById(userId);
		LoginWebVO loginWebVO = new LoginWebVO();
		if (loginUser != null) {
			BeanUtil.copyProperties(loginUser, loginWebVO);
		}
		loginWebVO.setScore(score);
		loginWebVO.setRank(rank);
		return loginWebVO;
    }

	/**
	 * 通过排名排行
	 * @param start
	 * @param end
	 * @param type 0 选手 1作品
	 * @return
	 */
    public List<LoginWebVO> reverseZRankWithRank(String activityId,long start, long end,Integer type) {
		String keyName = "";
    	if (type==0){
			keyName = KEY_USER;
		}else if(type==1){
			keyName = KEY_PRODUCTION;
		}
        Set<ZSetOperations.TypedTuple<Object>> setObj = redisService.reverseZRankWithRank(keyName+ activityId, start, end);
		if (CollUtil.isEmpty(setObj)) {
			return null;
//			if (type == 0) {
//				this.rankAddUser();
//			} else if (type == 1) {
//				this.rankAddProduction();
//			}
//			setObj = redisService.reverseZRankWithRank(keyName+ activityId, start, end);
		}else{
			return getMaps(activityId, setObj, type);
		}
	}

	/**
	 * 通过分数排行
	 *
	 * @param start
	 * @param end
	 * @return
	 */
	public List<LoginWebVO> rankWithScore(String activityId, long start, long end, Integer type) {
		Set<ZSetOperations.TypedTuple<Object>> setObj = redisService.reverseZRankWithScore(activityId, start, end);
		if (CollUtil.isEmpty(setObj)) {
			return null;
//			if (type == 0) {
//				this.rankAddUser();
//			} else if (type == 1) {
//				this.rankAddProduction();
//			}
//			setObj = redisService.reverseZRankWithScore(activityId, start, end);
		}else{
			return getMaps(activityId, setObj, type);
		}
	}

	public void  delProductKey(String key){
		redisService.remove(VALUE_PRODUCTION+key);
	}


	/**
	 * 移除指定缓存
	 * @param activityId 活动id
	 * @param valueId 0 userId 1 作品id
	 * @param type 0 作者 1作品
	 */
	public void zSetRemove(String activityId,String valueId,Integer type){
		String keyName;
		String valueName;
		if (type == 0) {
			keyName = KEY_USER;
			valueName = VALUE_USER;
		} else{
			keyName = KEY_PRODUCTION;
			valueName = VALUE_PRODUCTION;
		}
		redisService.zSetRemove((keyName + activityId),(valueName + valueId));
	}

	private List<LoginWebVO> getMaps(String activityId,Set<ZSetOperations.TypedTuple<Object>> setObj,Integer type) {
		List<LoginWebVO> loginWebVOList = setObj.stream().map(objectTypedTuple -> {
			Long valueId = Long.valueOf(objectTypedTuple.getValue().toString().split(":")[1]);
			String keyName = "";
			String valueName = "";
			Long userId = null;
			Long productionId=null;
			if (type == 0) {
				keyName = KEY_USER;
				valueName = VALUE_USER;
				userId = valueId;
			} else if (type == 1) {
				keyName = KEY_PRODUCTION;
				valueName = VALUE_PRODUCTION;
				productionId = valueId;
				userId=productionService.getById(valueId).getUserId();
			}
			Integer rank = redisService.zRank((keyName + activityId), valueName + valueId).intValue() + 1;
			LoginUser loginUser = loginUserService.getById(userId);
			LoginWebVO loginWebVO = new LoginWebVO();
			if (loginUser == null) {
				redisService.zSetRemove((keyName + activityId),(valueName + valueId));
				return null;
			}
			BeanUtil.copyProperties(loginUser, loginWebVO);
			loginWebVO.setScore(objectTypedTuple.getScore().toString());
			loginWebVO.setRank(rank);
			if (productionId != null) {
				Production production = productionService.getById(productionId);
				loginWebVO.setProduction(production);
			}
			return loginWebVO;
		}).filter(item->item!=null).collect(Collectors.toList());
		return loginWebVOList;
	}

//	@Override
//	public void afterPropertiesSet() throws Exception {
//		this.rankAddUser();
//		this.rankAddProduction();
//	}
}
