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

import com.duiba.tuia.youtui.web.constant.CacheKey;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.constant.LandChannel;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.model.req.VerificationCodeReq;
import com.duiba.tuia.youtui.web.service.SmsService;
import com.duiba.tuia.youtui.web.tool.CachedKeyUtils;
import com.duiba.tuia.youtui.web.tool.SmsUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;


/**
 * ClassName: SmsServiceImpl <br/>
 * Function: 短信验证码实现类. <br/>
 * date: 2017年03月28日  10:30:02 <br/>
 *
 * @author zdx
 * @version
 * @since JDK 1.7
 */
@Service
public class SmsServiceImpl implements SmsService {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    
    @Override
    public Boolean send(String phone,String channel) throws ActivityException {
    	VerificationCodeReq req = getVerificationCodeReq(phone, channel);
    	//1、安全验证：一分钟之内不能重复发送验证码
    	String repeatKey = CachedKeyUtils.getRedisKey(CacheKey.LAND_SMS_REPEAT, req.getPhone(), req.getChannel());
    	String repeatValue = stringRedisTemplate.opsForValue().get(repeatKey);
    	if (repeatValue != null) {
            logger.info("重复验证码，phone={}", req.getPhone());
            throw new ActivityException(ErrorCode.E0100002);
        }
    	stringRedisTemplate.opsForValue().set(repeatKey, req.getPhone(), req.getCodeGap(), TimeUnit.MINUTES);
    	
    	//2、生成验证码
    	String code = getRandomInt(req.getCodeLength());
    	
    	//3、发送验证码
        String text = req.getBeforeText() + code + req.getAfterText();
        logger.info("验证码信息  phone=[{}], channel=[{}], code=[{}]", req.getPhone(), req.getChannel(), code);
        SmsUtils.sendCodeSms(req.getPhone(), text);
        
        //4.存入缓存待验证 
        String codeKey = CachedKeyUtils.getRedisKey(CacheKey.LAND_SMS_CODE, req.getPhone(), req.getChannel());
    	stringRedisTemplate.opsForValue().set(codeKey, code, req.getExpire(), TimeUnit.MINUTES);

        return true;
    }

    @Override
    public Boolean verify(String phone, String code, String channel) {
    	String verifyKey = CachedKeyUtils.getRedisKey(CacheKey.LAND_SMS_CODE, phone, channel);
        String verifyCode = stringRedisTemplate.opsForValue().get(verifyKey);
        if (StringUtils.equals(code, verifyCode)) {
        	stringRedisTemplate.delete(verifyKey);
            return true;
        }
        return false;
    }
    
    /**
     * 生产验证码
     * @param length 验证码长度
     * @return
     */
    private static String getRandomInt(int length) {
        return String.valueOf((int) (ThreadLocalRandom.current().nextDouble(1, 10) * Math.pow(10, length - 1.0)));
    }
	
    /**
     * 组装发送验证码所需的参数
     * @param phone 手机
     * @param channel 渠道
     * @return
     */
    private VerificationCodeReq getVerificationCodeReq(String phone, String channel) {
        VerificationCodeReq req = null;
        String beforeText;
        String afterText;
        switch (channel) {
            case LandChannel.SJD_CHANNEL://手机贷
                beforeText = "【兑吧科技】您的验证码是：";
                afterText = "，快去领取手机贷新手专属权益吧！";
                req = new VerificationCodeReq(channel, phone, beforeText, afterText, VerificationCodeReq.ONE_MINUTE, VerificationCodeReq.TEN_MINUTES, VerificationCodeReq.SMS_CODE_LENGTH);
                break;
            default:
                beforeText = "【兑吧科技】您的验证码是：";
                afterText = "";
                req = new VerificationCodeReq(channel, phone, beforeText, afterText, VerificationCodeReq.ONE_MINUTE, VerificationCodeReq.TEN_MINUTES, VerificationCodeReq.SMS_CODE_LENGTH);
                break;
        }
        return req;
    }

}
