package cn.quantgroup.xyqb.aspect.captcha;

import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.model.ClientType;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.captcha.IGeetestCaptchaService;
import cn.quantgroup.xyqb.service.captcha.IQuantgroupCaptchaService;
import cn.quantgroup.xyqb.util.IpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.Optional;

/**
 * @author xufei on 2018/1/30.
 */
@Aspect
@Component
@Slf4j
public class CaptchaNewValidateAdvisor {

    @Resource
    private IGeetestCaptchaService geetestCaptchaService;
    @Resource
    private IQuantgroupCaptchaService quantgroupCaptchaService;

    /**
     * 图形验证码切面
     */
    @Pointcut("@annotation(cn.quantgroup.xyqb.aspect.captcha.CaptchaNewValidator)")
    private void needCaptchaValidate() {
    }

    /**
     * 在受图形验证码保护的接口方法执行前, 校验图形验证码
     *
     * @param pjp pjp
     * @return
     * @throws Throwable
     */
    @Around("needCaptchaValidate()")
    private Object doCaptchaValidate(ProceedingJoinPoint pjp) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 验证码类别：gt - 极验，qg - 量化派图形验证
        if (Objects.equals(Constants.VERIFY_TYPE_GT, request.getParameter(Constants.VERIFY_PARAM))) {
            if (StringUtils.isBlank(request.getParameter(Constants.FN_GEETEST_CHALLENGE))) {
                return JsonResult.buildErrorStateResult("操作过快，请稍后重试", "");
            }
            if (gtValid(request)) {
                return pjp.proceed();
            } else {
                return JsonResult.buildErrorStateResult("验证码不正确", "");
            }
        } else {
            if (qgValid(request)) {
                return pjp.proceed();
            } else {
                return JsonResult.buildErrorStateResult("验证码不正确", "", 2L);
            }
        }
    }

    /**
     * 极验校验
     *
     * @param request
     * @return
     * @throws Throwable
     */
    private boolean gtValid(HttpServletRequest request) {
        String uniqueKey = request.getParameter(Constants.GT_UNIQUE_KEY);
        String phoneNo = request.getParameter(Constants.PHONE_NO);
        String clientType = request.getParameter(Constants.CLIENT_TYPE);
        String challenge = request.getParameter(Constants.FN_GEETEST_CHALLENGE);
        String validate = request.getParameter(Constants.FN_GEETEST_VALIDATE);
        String seccode = request.getParameter(Constants.FN_GEETEST_SECCODE);
        log.info("Geetest - 极验二次校验, phoneNo:{}, uniqueKey:{}, clientType:{}, ip:{}, challenge:{}, validate:{}, seccode:{}", phoneNo, uniqueKey, clientType, IpUtil.getRemoteIP(request), challenge, validate, seccode);
        return geetestCaptchaService.validGeetestCaptcha(uniqueKey, IpUtil.getRemoteIP(request), ClientType.valueByName(clientType), challenge, validate, seccode);
    }

    /**
     * 量化派图形码校验
     *
     * @param request
     * @return
     * @throws Throwable
     */
    private boolean qgValid(HttpServletRequest request) {
        String phoneNo = request.getParameter(Constants.PHONE_NO);
        String captchaId = Optional.ofNullable(request.getParameter(Constants.QG_CAPTCHA_ID)).orElse("");
        String captchaValue = request.getParameter(Constants.QG_CAPTCHA_VALUE);
        log.info("Quantgroup - 图形验证码校验, phoneNo:{}, ip:{}, captchaId:{}, captchaValue:{}", phoneNo, IpUtil.getRemoteIP(request), captchaId, captchaValue);
        return quantgroupCaptchaService.validQuantgroupCaptcha(captchaId, captchaValue);
    }

}
