package com.bizzan.bitrade.controller;

import com.alibaba.fastjson.JSONObject;
import com.bizzan.bitrade.constant.SysConstant;
import com.bizzan.bitrade.controller.BaseController;
import com.bizzan.bitrade.entity.Member;
import com.bizzan.bitrade.entity.transform.AuthMember;
import com.bizzan.bitrade.service.LocaleMessageSourceService;
import com.bizzan.bitrade.service.MemberService;
import com.bizzan.bitrade.util.GoogleAuthenticatorUtil;
import com.bizzan.bitrade.util.Md5;
import com.bizzan.bitrade.util.MessageResult;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.manager.util.SessionUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

import static com.bizzan.bitrade.constant.SysConstant.SESSION_MEMBER;
import static org.springframework.util.Assert.hasText;
import static org.springframework.util.Assert.isTrue;
import static org.springframework.util.Assert.notNull;

import java.util.Calendar;
import java.util.Date;

/**
 * @author QQ 2232965526
 * @time 2020.04.09 11:07
 */
@Api(value = "GoogleAuthenticationController" , tags = "谷歌认证接口")
@RestController
@Slf4j
@RequestMapping("/google")
public class GoogleAuthenticationController extends BaseController{

    @Autowired
    private MemberService memberService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private LocaleMessageSourceService msService;

    /**
     * 验证google
     * @author QQ 2232965526
     * @time 2020.04.09 11:36
     * @param user
     * @param codes
     * @return true
     */

    @ApiOperation(value="验证谷歌码", notes="验证谷歌码")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "codes",value = "谷歌码",required = true,dataType = "string")
    })
    @RequestMapping(value = "/yzgoogle",method = RequestMethod.GET)
    public MessageResult yzgoogle(@SessionAttribute(SESSION_MEMBER) AuthMember user,String codes) {
        // enter the code shown on device. Edit this and run it fast before the
        // code expires!
        long code = Long.parseLong(codes);
        Member member = memberService.findOne(user.getId());
        long t = System.currentTimeMillis();
        GoogleAuthenticatorUtil ga = new GoogleAuthenticatorUtil();
        //  ga.setWindowSize(0); // should give 5 * 30 seconds of grace...
        boolean r = ga.check_code(member.getGoogleKey(), code, t);
        System.out.println("rrrr="+r);
        if(!r){
            return MessageResult.error(msService.getMessage("GOOGLE_CODE_EXPIRED"));
        } else {
            return MessageResult.success("验证通过");
        }
    }


    /**
     * 生成谷歌认证码
     * @return
     */
    @ApiOperation(value="生成谷歌认证码", notes="生成谷歌认证码")
    @RequestMapping(value = "/sendgoogle",method = RequestMethod.GET)
    public MessageResult  sendgoogle(@SessionAttribute(SESSION_MEMBER) AuthMember user) {
        /*for(int i = 0;i<50;i++){
            log.info("######################       开始循环次数={}    ######################",i+1);
            GoogleAuthenticatorUtil.generateSecretKey();
            log.info("######################       结束循环次数={}    ######################",i+1);
        }*/
        log.info("开始进入用户id={}",user.getId());
        long current = System.currentTimeMillis();
        Member member = memberService.findOne(user.getId());
        log.info("查询完毕 耗时={}",System.currentTimeMillis()-current);
        if (member == null){
            return  MessageResult.error(msService.getMessage("RE_LOGIN"));
        }
        String secret = GoogleAuthenticatorUtil.generateSecretKey();
        log.info("secret完毕 耗时={}",System.currentTimeMillis()-current);
        String qrBarcodeURL = GoogleAuthenticatorUtil.getQRBarcodeURL(member.getId().toString(),
                "IBit", secret);
        log.info("qrBarcodeURL完毕 耗时={}",System.currentTimeMillis()-current);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("link",qrBarcodeURL);
        jsonObject.put("secret",secret);
        log.info("jsonObject完毕 耗时={}",System.currentTimeMillis()-current);
        MessageResult messageResult = new MessageResult();
        messageResult.setData(jsonObject);
        messageResult.setMessage("获取成功");
        log.info("执行完毕 耗时={}",System.currentTimeMillis()-current);
        return  messageResult;

    }


    /**
     * google解绑
     * @author QQ 2232965526
     * @time 2020.04.09 12:47
     * @param codes
     * @param user
     * @return true
     */
    @ApiOperation(value="解绑", notes="解绑")
    @RequestMapping(value = "/jcgoogle" ,method = RequestMethod.POST)
    public MessageResult jcgoogle(String codes, @SessionAttribute(SESSION_MEMBER) AuthMember user,String password) {
        // enter the code shown on device. Edit this and run it fast before the
        // code expires!
        //String GoogleKey = (String) request.getSession().getAttribute("googleKey");
        Member member = memberService.findOne(user.getId());
        String GoogleKey = member.getGoogleKey();
        if(StringUtils.isEmpty(password)){
            return MessageResult.error(msService.getMessage("MISSING_LOGIN_PASSWORD"));
        }
        try {
            if(!(Md5.md5Digest(password + member.getSalt()).toLowerCase().equals(member.getPassword().toLowerCase()))){
                return MessageResult.error(msService.getMessage("PASSWORD_ERROR"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long code = Long.parseLong(codes);
        long t = System.currentTimeMillis();
        GoogleAuthenticatorUtil ga = new GoogleAuthenticatorUtil();
        // ga.setWindowSize(0); // should give 5 * 30 seconds of grace...
        boolean r = ga.check_code(GoogleKey, code, t);
        if(!r){
            return MessageResult.error(msService.getMessage("GOOGLE_CODE_EXPIRED"));
        } else {
            member.setGoogleDate(new Date());
            member.setGoogleState(0);
            Member result = memberService.save(member);
            if(result != null){
                return MessageResult.success(msService.getMessage("GOOGLE_UNBIND_SUCCESS"));
            } else {
                return MessageResult.error(msService.getMessage("GOOGLE_UNBIND_FAILED"));
            }
        }
    }




        //ga.setWindowSize(0); // should give 5 * 30 seconds of grace...
        /**
         * 绑定google
         * @author QQ 2232965526
         * @time 2020.04.09 15:19
         * @param codes
         * @param user
         * @return true
         */
        //@RequestMapping(value = "/googleAuth" ,method = RequestMethod.POST)
        public MessageResult googleAuth(String codes, @SessionAttribute(SESSION_MEMBER) AuthMember user,String secret) {

            Member member = memberService.findOne(user.getId());
            long code = Long.parseLong(codes);
            long t = System.currentTimeMillis();
            GoogleAuthenticatorUtil ga = new GoogleAuthenticatorUtil();
            boolean r = ga.check_code(secret, code, t);
            if(!r){
                return MessageResult.error(msService.getMessage("GOOGLE_CODE_EXPIRED"));
            } else {
                member.setGoogleState(1);
                member.setGoogleKey(secret);
                member.setGoogleDate(new Date());
                Member result = memberService.save(member);
                if(result != null){
                    return MessageResult.success(msService.getMessage("GOOGLE_BIND_SUCCESS"));
                } else {
                    return MessageResult.error(msService.getMessage("GOOGLE_BIND_FAILED"));
                }
            }
        }

        @ApiOperation(value="谷歌认证，需要手机或邮箱验证码", notes="谷歌认证，需要手机或邮箱验证码")
        @ApiImplicitParams(value = {
        		@ApiImplicitParam(name = "codes",value = "谷歌码",required = true,dataType = "string"),
        		@ApiImplicitParam(name = "secret",value = "密钥",required = true,dataType = "string"),
        		@ApiImplicitParam(name = "vtype",value = "验证类型",required = true,dataType = "int"),
        		@ApiImplicitParam(name = "vcode",value = "验证码",required = true,dataType = "string")
        })
        @RequestMapping(value = "/googleAuthWithSms" ,method = RequestMethod.POST)
        public MessageResult googleAuthWithSms(String codes, @SessionAttribute(SESSION_MEMBER) AuthMember user,String secret, Integer vtype, String vcode) {

            Member member = memberService.findOne(user.getId());
            
            if(vtype == 1) {
            	ValueOperations valueOperations = redisTemplate.opsForValue();
                Object cache = valueOperations.get(SysConstant.PHONE_AUTH_GOOGLE_PREFIX + member.getMobilePhone());
//                notNull(cache, msService.getMessage("NO_GET_VERIFICATION_CODE"));
                if(null == cache){
                    return MessageResult.error(msService.getMessage("NO_GET_VERIFICATION_CODE"));
                }
                if (!StringUtils.hasText(vcode)) {
                    return MessageResult.error(msService.getMessage("MISSING_VERIFICATION_CODE"));
                }
//                hasText(vcode, msService.getMessage("MISSING_VERIFICATION_CODE"));
                if (!vcode.equals(cache.toString())) {
                    return MessageResult.error(msService.getMessage("VERIFICATION_CODE_INCORRECT"));
                } else {
                    valueOperations.getOperations().delete(SysConstant.PHONE_AUTH_GOOGLE_PREFIX + member.getMobilePhone());
                }
            } else if (vtype == 2) {
            	ValueOperations valueOperations = redisTemplate.opsForValue();
                Object cache = valueOperations.get(SysConstant.EMAIL_AUTH_GOOGLE_PREFIX + member.getEmail());
                if(null == cache){
                    return MessageResult.error(msService.getMessage("NO_GET_VERIFICATION_CODE"));
                }
//                notNull(cache, msService.getMessage("NO_GET_VERIFICATION_CODE"));
                if(!vcode.equals(cache.toString())){
                    return MessageResult.error(msService.getMessage("VERIFICATION_CODE_INCORRECT"));
                }
//                isTrue(vcode.equals(cache.toString()), msService.getMessage("VERIFICATION_CODE_INCORRECT"));
            } else {
            	return MessageResult.error(msService.getMessage("VERIFICATION_CODE_INCORRECT"));
            }
            
            
            long code = Long.parseLong(codes);
            long t = System.currentTimeMillis();
            GoogleAuthenticatorUtil ga = new GoogleAuthenticatorUtil();
            boolean r = ga.check_code(secret, code, t);
            if(!r){
                return MessageResult.error(msService.getMessage("GOOGLE_CODE_EXPIRED"));
            } else {
            	if (member.getGoogleState() != null && member.getGoogleState() == 1) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.add(Calendar.DATE, 2);
                    member.setMoneyLockTime(calendar.getTime());
            	}
                member.setGoogleState(1);
                member.setGoogleKey(secret);
                member.setGoogleDate(new Date());
                Member result = memberService.save(member);
                if(result != null){
                    return MessageResult.success(msService.getMessage("GOOGLE_BIND_SUCCESS"));
                } else {
                    return MessageResult.error(msService.getMessage("GOOGLE_BIND_FAILED"));
                }
            }
        }

}
