/**
 * Project Name:tuia-youtui-web<br>
 * File Name:ConsumerBOImpl.java<br>
 * Package Name:com.duiba.tuia.youtui.web.bo.impl<br>
 * Date:2017年1月22日上午9:56:09<br>
 * Copyright (c) 2017, duiba.com.cn All Rights Reserved.<br>
 */

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

import cn.com.duiba.tuia.activity.center.api.cache.CacheSpace;
import cn.com.duiba.tuia.activity.center.api.constant.BalanceType;
import cn.com.duiba.tuia.activity.center.api.dto.NickNameDto;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.ConsumerCache;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.ConsumerDto;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.UserBalanceDto;
import cn.com.duiba.tuia.activity.center.api.remoteservice.RemoteBalanceRecordService;
import cn.com.duiba.tuia.activity.center.api.remoteservice.RemoteTuiaUserService;
import cn.com.duiba.wolf.dubbo.DubboResult;
import com.alibaba.fastjson.JSONObject;
import com.duiba.tuia.youtui.web.constant.CacheKey;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.model.UserAccount;
import com.duiba.tuia.youtui.web.service.BaseCacheService;
import com.duiba.tuia.youtui.web.service.ConsumerService;
import com.duiba.tuia.youtui.web.service.UserBalanceService;
import com.duiba.tuia.youtui.web.tool.CachedKeyUtils;
import com.duiba.tuia.youtui.web.tool.MD5;
import com.duiba.tuia.youtui.web.tool.RequestLocal;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * ClassName: ConsumerBOImpl <br/>
 * Function: 用户. <br/>
 * date: 2017年1月22日 上午9:56:09 <br/>
 *
 * @author leiliang
 * @since JDK 1.6
 */
@Service
public class ConsumerServiceImpl extends BaseCacheService implements ConsumerService {

    public static final String SYSTEM_NAME = "PGW";

    public static final String TAW_NICKNAME = "TN";
    @Autowired
    private RemoteTuiaUserService remoteTuiaUserService;

    @Autowired
    private UserBalanceService userBalanceService;

    @Autowired
    private RemoteBalanceRecordService remoteBalanceRecordService;

    @Override
    public UserAccount getOrMakeUser(Long appId, String partnerUserId) throws ActivityException {

        // 1.查询用户信息缓存
        UserAccount userAccount = new UserAccount(appId, partnerUserId);
        if(RequestLocal.get().getLoginStatus()){
            return userAccount;
        }
        String accountKey = CachedKeyUtils.getRedisKey(CacheKey.USER_ACCOUNT_KEY, appId, partnerUserId);
        String strConsumerId = redisTemplate03.opsForValue().get(accountKey);
        Long userId;

        // 2.判断是否有用户信息，有直接返回
        if (StringUtils.isNotEmpty(strConsumerId)) {
            // 更新Cookie
            userId = Long.valueOf(strConsumerId.toString());
            userAccount.setUserId(userId);
            RequestLocal.get().setCookie(userAccount);
            return userAccount;
        }

        // 3.无当前用户信息，查询或创建一个用户ID
        DubboResult<Long> ret = remoteTuiaUserService.findByAppIdAndDeviceId(appId, partnerUserId);
        if (!ret.isSuccess()) {
            throw new ActivityException(ErrorCode.E0200001);
        }
        userId = ret.getResult();

        // 4.用户非空 ， 赋值userId
        if (userId == null) {
            throw new ActivityException(ErrorCode.E0200002);
        }

        // 5.生成cookie
        userAccount.setUserId(userId);

        // 更新用户信息缓存
        redisTemplate03.opsForValue().set(accountKey, String.valueOf(userId).trim(), FIVE_MIN, TimeUnit.SECONDS);

        RequestLocal.get().setCookie(userAccount);
        return userAccount;
    }

    @Override
    public ConsumerDto findFormalConsumer(Long appId, String phone, String muId) {
        ConsumerDto consumerDto = new ConsumerDto(appId, null);
        consumerDto.setPhone(phone);
        consumerDto.setMuId(muId);
        return remoteTuiaUserService.findFormalConsumer(consumerDto);
    }

    @Override
    public Long findCasualConsumer(Long appId, String deviceId) {
        return remoteTuiaUserService.findCasualConsumer(new ConsumerDto(appId, deviceId));
    }

    @Override
    public String getRegisterVerCode(String phone) {
        return advancedCacheClient.get(CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_REGISTER_VER_CODE, phone));
    }

    @Override
    public void setRegisterVerCode(String phone, String verCode) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        advancedCacheClient.set((CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_REGISTER_VER_CODE, phone)), MD5.md5(verCode), 30, TimeUnit.MINUTES);
    }

    @Override
    public boolean isYiDunVerifyList(String userId) {
        String redisKey = CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_LIST_FOR_YIDUN);
        return stringRedisTemplate.opsForSet().isMember(redisKey, userId).booleanValue();
    }

    @Override
    public void setConsumerCache(ConsumerCache cache) {
        String key = ConsumerCache.REDIS_KEY + cache.getUserId();
        stringRedisTemplate.opsForValue().set(key, cache.toJsonString(), 1, TimeUnit.DAYS);
    }

    @Override
    public ConsumerCache getConsumerCache(Long userId) {
        ConsumerCache consumerCache = JSONObject.parseObject(stringRedisTemplate.opsForValue().get(ConsumerCache
                        .REDIS_KEY + userId),
                ConsumerCache.class);
        if(null == consumerCache){
            return remoteTuiaUserService.getConsumerById(userId).toConsumerCache();
        }
        return consumerCache;
    }

    @Override
    public ConsumerCache getConsumerCache4WX(String openId) {
        String key = new StringBuilder(SYSTEM_NAME).append("_").append(TAW_NICKNAME).append("_").append(openId).toString();
        return ConsumerCache.parseJsonString(stringRedisTemplate.opsForValue().get(key));
    }

    @Override
    public void setTodayFirstGive(String userId, Long amount) {
        stringRedisTemplate.opsForValue().set(CacheSpace.GAME_DAILY_GIVE.generatorKey(userId),amount.toString());
        stringRedisTemplate.expire(CacheSpace.GAME_DAILY_GIVE.generatorKey(userId), getRestSecondsToday(), TimeUnit.SECONDS);
    }

    @Override
    public boolean isFirstGive(Long userId, BalanceType balanceType) {

        UserBalanceDto balanceDto = userBalanceService.getByType(userId, balanceType);
        return null == remoteBalanceRecordService.getFirstLoginRecord(userId, balanceDto.getBalanceId(), balanceType);
    }

    @Override
    public boolean isTodayFirstGive(String userId) {
        return StringUtils.isNotBlank(stringRedisTemplate.opsForValue().get(CacheSpace.GAME_DAILY_GIVE.generatorKey
                (userId)));
    }

    @Override
    public void setYiDunVerifyList(String userId) {
        String redisKey = CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_LIST_FOR_YIDUN);
        if (0 == stringRedisTemplate.opsForSet().size(redisKey)) {
            stringRedisTemplate.expire(redisKey, getRestSecondsToday(), TimeUnit.SECONDS);
        }
        stringRedisTemplate.opsForSet().add(redisKey, userId);
    }

    @Override
    public int getSmsTimes(String key) {
        Object o = advancedCacheClient.get(CachedKeyUtils.getRedisKey(CacheKey.SMS_TIMES, key));
        if (null == o) {
            return 0;
        }
        return (int) o;
    }

    @Override
    public void setSmsTimes(String key, int times) {
        advancedCacheClient.set((CachedKeyUtils.getRedisKey(CacheKey.SMS_TIMES, key)), times, getRestSecondsToday(), TimeUnit.SECONDS);
    }

    @Override
    public int getSmsTotalTimes() {
        Object o = advancedCacheClient.get(CachedKeyUtils.getRedisKey(CacheKey.SMS_TIMES));
        if (null == o) {
            return 0;
        }
        return (int) o;
    }

    @Override
    public void setSmsTotalTimes(int times) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        advancedCacheClient.set((CachedKeyUtils.getRedisKey(CacheKey.SMS_TIMES)), times, getRestSecondsToday(), TimeUnit.SECONDS);
    }

    @Override
    public void updateLoginTryTimes(String userId) {
        String redisKey = CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_LOGIN_TRY_TIMES, userId);
        Long increment = stringRedisTemplate.opsForValue().increment(redisKey, 1);
        if (1 == increment) {
            stringRedisTemplate.expire(redisKey, 5, TimeUnit.MINUTES);
        }
    }

    @Override
    public int getLoginTryTimes(String userId) {
        String redisKey = CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_LOGIN_TRY_TIMES, userId);
        String s = stringRedisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isBlank(s)) {
            return 0;
        }
        return Integer.valueOf(s);
    }

    @Override
    public ConsumerDto getOrCreateConsumer(ConsumerDto req) throws ActivityException {
        if(req.getDeviceId()!=null&&req.getDeviceId().length()>64){
            logger.warn("device warning {}", ToStringBuilder.reflectionToString(req));
        }
        ConsumerDto consumer = remoteTuiaUserService.findOrCreateConsumer(req);
        if (null == consumer) {
            throw new ActivityException(ErrorCode.E9999999.geteCode(), "注册失败,请稍后重试.");
        }
        return consumer;
    }

    @Override
    public String getVisitorNickName(int length, int zero){
        String str = "游客";
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            boolean b = random.nextBoolean();
            if (b) { // 字符串
//                int choice = random.nextBoolean() ? 65 : 97; //取得65大写字母还是97小写字母
                str += (char) (97 + random.nextInt(26));
            } else { // 数字
                str += String.valueOf(random.nextInt(10));
            }
        }
        //直接保存昵称，如果保存失败，则为重复昵称，重新随机一个昵称
        if (!remoteTuiaUserService.insertAndUsedNickName(str)) {
            if (zero < 3) {
                //重试3次
                str = getVisitorNickName(length, ++zero);
            }
        }
        return str;
    }

    @Override
    public boolean updateConsumer(ConsumerDto req) throws ActivityException {
        Boolean result = remoteTuiaUserService.updateConsumer(req);
        if (null == result || !result) {
            throw new ActivityException(ErrorCode.E9999999.geteCode(), "重置失败,请稍后重试");
        }
        return result;
    }

    @Override
    public ConsumerDto getConsumerById(Long userId){
        return remoteTuiaUserService.getConsumerById(userId);
    }

    @Override
    public NickNameDto getNextNickName(Long id) {
        return remoteTuiaUserService.getNext(id);
    }

    @Override
    public boolean confirmNickName(String nickName){
        return remoteTuiaUserService.confirmNickName(nickName);
    }

}
