package com.duiba.tuia.youtui.web.service;

import cn.com.duiba.wolf.cache.AdvancedCacheClient;
import cn.com.duiba.wolf.perf.timeprofile.DBTimeProfile;
import com.duiba.tuia.youtui.web.constant.CacheKey;
import com.duiba.tuia.youtui.web.tool.ConsumerTokenUtil;
import com.duiba.tuia.youtui.web.tool.FileIDGenerator;
import com.duiba.tuia.youtui.web.tool.RequestLocal;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 表单token操作服务
 * @author xuhengfei
 *
 */
@Service
public class TokenService extends BaseService implements InitializingBean{
	private static final String TEST_TKEN = "yrJRr7Cddp2YeQd";

	@Resource(name="redisTemplate")
	private AdvancedCacheClient advancedCacheClient;

	private LoadingCache<String,String> tokenCache;

	@Override
	public void afterPropertiesSet() {
		tokenCache = CacheBuilder
				.newBuilder()
				.maximumSize(1000)
				.expireAfterAccess(1, TimeUnit.MINUTES)
				.build(new CacheLoader<String, String>() {
					@Override
					public String load(String s) {
						return generate();
					}
				});
	}

	/**
	 * 从内存缓存中 获取最新token
	 * @param cid
	 * @return
	 */
	public String getConsumerTokenFromCache(Long cid) {
		return tokenCache.getUnchecked(getConsumerKey(cid));
	}

	/**
	 * 校验token
	 * 逻辑:
	 * 1.token为空直接失败
	 * 2.token 与 缓存中的token去校验
	 * 3.校验失败返回false，校验成功生成新的token set到缓存中，留着下次用
	 *
	 * @param cid 用户id
	 * @param token token
	 * @return boolean
	 */
	public boolean checkAndInvalidConsumerTokenFromCache(Long cid, String token) {
		return StringUtils.isNotBlank(token) && (StringUtils.equals(token, tokenCache.getUnchecked(getConsumerKey(cid))) || ConsumerTokenUtil.TEMP_TOKEN.equals(token)) && putNewToken(cid);
	}

	private boolean putNewToken(Long cid) {
		tokenCache.put(getConsumerKey(cid), generate());
		return true;
	}

	/**
	 * 获取商城用户的form token
	 * @param cid
	 * @return
	 */
	public String getConsumerToken(Long cid){
		String key = getConsumerKey(cid);
		String token=generate();
		int exp=15;//15分钟内有效
		advancedCacheClient.set(key, token,exp,TimeUnit.MINUTES);
		return token;
	}

	/**
	 * 验证token并进行失效操作
	 * @param cid
	 * @param token
	 * @return
	 */
	public boolean checkAndInvalidConsumerToken(Long cid,String token){
		try {
			DBTimeProfile.enter("checkAndInvalidConsumerToken");
			if(token==null){
				return false;
			}
			// 如果是测试的token，那么默认可用
			if (TEST_TKEN.equals(token)) {
				return true;
			}
			String key = getConsumerKey(cid);
			String memToken = advancedCacheClient.get(key);
			if(memToken==null){
				return false;
			}
			advancedCacheClient.remove(key);
			return memToken.equals(token);
		} finally {
			DBTimeProfile.release();
		}
	}


	private String generate(){
		int length=new Random().nextInt(5)+5;
		return FileIDGenerator.getRandomString(length);
	}

	private String getConsumerKey(Long cid){
		return CacheKey.CONSUMER_TOKEN+"-"+cid;
	}


}