package com.palmnest.service.impl;

import com.palmnest.application.Constants;
import com.palmnest.application.core.util.DateUtils;
import com.palmnest.dao.UserActiveDao;
import com.palmnest.model.UserActiveCount;
import com.palmnest.service.UserActiveManager;
import com.palmnest.service.redis.BaseRedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;

/**
 * @Author hxt
 * @Description TODO
 * @Date 2019/1/11 11:15
 **/
@Slf4j
@Service("userActiveManager")
public class UserActiveManagerImpl extends GenericManagerImpl<UserActiveCount, Long> implements UserActiveManager {

	private UserActiveDao userActiveDao;

	@Autowired
	public void setUserActiveDao(UserActiveDao userActiveDao) {
		this.userActiveDao = userActiveDao;
	}

	@Autowired
	private BaseRedisService redisService;


	@Async
	public void saveModuleUserToLocal() {
		try {
			// 获取今天的日期字符串 yyyy-MM-dd
			String todayStr = DateUtils.getDate("");
			// 获取今天总的活跃量 格式: moduleActive:yyyy-MM-dd
			String todayKey = Constants.MODULE_ACTIVE.concat(":").concat(todayStr);

			// 获取所有的活跃量
			Set<String> allKeySet = redisService.getKeyValues(Constants.MODULE_ACTIVE.concat(":"));

			log.info("saveModuleUserToLocal ====>所有统计数据 allKeySet:{}", allKeySet.toString());
			if (allKeySet != null && allKeySet.size() > 0) {
				// 每天活跃的项目集合 例: moduleActive:yyyy-MM-dd:orgId
				Set<String> orgDaySet = new HashSet<>();

				// ------------------ 统计并保存每天每个项目每个模块的有效活跃量 ------------------
				for (String key : allKeySet) {
					if (key.indexOf("total") != -1) {
						// 项目活跃总数,非模块统计数据,则跳过
						continue;
					}

					// 统计活跃量
					Long     count = redisService.bitCount(key);
					String[] split = key.split(":");
					// 模块名称
					String serviceCode = split[3];
					// 项目id
					String orgId = split[2];
					// 日期
					String date = split[1];

					orgDaySet.add(key.substring(0, key.lastIndexOf(":")));
					log.info("======= key:{},count:{},serviceCode:{},orgId:{},date:{}", key, count, serviceCode, orgId, date);

					// 保存数据库操作 保存时间/服务编码/活跃量 信息
					// 如果数据库存在 该日期/该项目/该服务 的活跃量信息 则进行修改;否则进行保存;
					UserActiveCount userActiveCount = userActiveDao.getCountByDateAndOrgAndserviceCode(date, orgId, serviceCode);
					if (userActiveCount != null) {
						userActiveCount.setCount(count.intValue());
						userActiveDao.updateObj(userActiveCount);
					} else {
						userActiveCount = new UserActiveCount();
						userActiveCount.setCount(count.intValue());
						userActiveCount.setServiceCode(serviceCode);
						userActiveCount.setDate(DateUtils.getDateByString(date, DateUtils.YYYY_MM_DD));
						userActiveCount.setOrgId(Integer.parseInt(orgId));
						userActiveDao.save(userActiveCount);
					}
				}

				// ------------------ 统计并保存每个项目每天的有效活跃量 ------------------
				log.info("saveModuleUserToLocal ====>项目活跃数据 orgDaySet:{}", orgDaySet.toString());
				for (String orgKey : orgDaySet) {
					// 项目id
					String orgId = orgKey.split(":")[2];
					// 日期
					String date = orgKey.split(":")[1];
					// 模块名称
					String serviceCode = "total";

					// 获取当天项目所有模块的用户统计量: moduleActive:yyyy-MM-dd:orgId:FW-xxx
					Set<String> orgKeySet = redisService.getKeyValues(orgKey);
					String[]    keyArr    = new String[orgKeySet.size()];
					// 统计每个项目有效活跃量:用redis bitMap的bitOp操作求每个项目的总活跃量,将结果保存在新的bitMap中
					// 格式为: moduleActive:total:yyyy-MM-dd:orgId
					String totalKey = Constants.MODULE_ACTIVE + ":" + serviceCode + ":" + date + ":" + orgId;

					redisService.bitOp(RedisStringCommands.BitOperation.OR, totalKey, orgKeySet.toArray(keyArr));
					Long aLong = redisService.bitCount(totalKey);
					// 保存项目每天的有效活跃量
					// 如果数据库存在 该日期/该项目/该服务 的活跃量信息 则进行修改;否则进行保存;
					UserActiveCount userActiveCount = userActiveDao.getCountByDateAndOrgAndserviceCode(date, orgId, serviceCode);
					if (userActiveCount != null) {
						userActiveCount.setCount(aLong.intValue());
						userActiveDao.updateObj(userActiveCount);
					} else {
						userActiveCount = new UserActiveCount();
						userActiveCount.setCount(aLong.intValue());
						userActiveCount.setServiceCode(serviceCode);
						userActiveCount.setDate(DateUtils.getDateByString(date, DateUtils.YYYY_MM_DD));
						userActiveCount.setOrgId(Integer.parseInt(orgId));
						userActiveDao.save(userActiveCount);
					}

					// 最后删除redis中除过今天且已经被同步到数据库的数据(因为今天的数据还得保留)
					if (!orgKey.contains(todayKey)) {
						redisService.delKeyLike(orgKey);
						redisService.delKeyLike(totalKey);
					}
				}

			}
		} catch (Exception e) {
			log.error("UserActiveManagerImpl saveModuleUserToLocal=======>" + e.getMessage());
		}
	}

}
