package cn.quantgroup.xyqb.controller.internal.user;

import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.accessable.IpValidator;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.exception.VerificationCodeErrorException;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.session.SessionStruct;
import cn.quantgroup.xyqb.service.session.ISessionService;
import cn.quantgroup.xyqb.service.sms.ISmsService;
import cn.quantgroup.xyqb.service.user.IUserService;
import cn.quantgroup.xyqb.session.XyqbSessionContextHolder;
import cn.quantgroup.xyqb.util.ValidationUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * Created by FrankChow on 15/12/16.
 */
@Slf4j
@RestController
@RequestMapping("/api")
public class UserApiController {

    @Resource
    private IUserService userService;
    @Resource
    private ISessionService sessionService;
    @Resource
    @Qualifier("stringRedisTemplate")
    private RedisTemplate<String, String> stringRedisTemplate;
    @Resource
    private ISmsService smsService;

    @RequestMapping("/user/is_passwd_set")
    public JsonResult isPasswordSet(String phoneNo) {
        if (StringUtils.isEmpty(phoneNo)) {
            return JsonResult.buildErrorStateResult(null, null);
        }
        User user = userService.findByPhoneWithCache(phoneNo);
        if (null == user) {
            return JsonResult.buildErrorStateResult(null, null);
        }
        if (StringUtils.length(user.getPassword()) == Constants.MD5_LENGTH) {
            return JsonResult.buildSuccessResult(null, null);
        }
        return JsonResult.buildErrorStateResult(null, null, 2L);
    }

    /**
     * 检查token是否有效
     * 如果有效，可选择是否延续生命期（延续后有效期24Hour）
     *
     * @param token   - sid,session的id
     * @param prolong - 是否延续生命期，可选参数，默认为: false - 不延续
     * @return
     */
    @ApiOperation(notes = "检查token是否有效，如果有效，可选择是否延续生命期（延续后有效期24Hour）", value = "Check token and then prolong session", nickname = "checkToken")
    @IpValidator
    @RequestMapping(value = "/valid/{token}", method = RequestMethod.POST)
    public JsonResult checkToken(@ApiParam(value = "sid,session的id", required = true)
                                 @PathVariable("token") String token,
                                 @ApiParam(value = "是否延续生命期，可选参数，默认为: false - 不延续")
                                 @RequestParam(name = "prolong", required = false, defaultValue = "false") Boolean prolong,
                                 @RequestParam(name = "prolongTime", required = false, defaultValue = "86400") Long prolongTime) {
        if (Objects.isNull(token) || !ValidationUtil.validateToken(token)) {
            return JsonResult.buildErrorStateResult("token invalid", token);
        }
        String tokenKey = Constants.SESSION_PREFIX + token;
        String tokenKey2 = Constants.Session.USER_SESSION_CACHE + token;
        // 判断token是否存在
        boolean exist = stringRedisTemplate.hasKey(tokenKey) || stringRedisTemplate.hasKey(tokenKey2);
        log.info("检查token:[{}]有效性[{}]，延续生命期[{}]", token, exist, prolong);
        /* token存在且需要延续时，进一步判断session是否有效，有效时，自动续期 */
        if (Boolean.logicalAnd(exist, prolong)) {
            // 获取session信息
            SessionStruct sessionStruct = XyqbSessionContextHolder.getXSessionFromRedis(token);
            if (Objects.isNull(sessionStruct)) {
                log.info("延续token:[{}]生命期,result：[{}],SessionStruct：{}", token, false, sessionStruct);
                /* 如果没有获取到session信息则返回错误信息 */
                return JsonResult.buildErrorStateResult("session invalid", token);
            } else {
                /* 延续session生命期 */
                try {
                    sessionService.persistSession(sessionStruct.getSid(), sessionStruct.getValues(), prolongTime);
                    log.info("延续token:[{}]生命期,result：[{}]", token, true);
                } finally {
                    XyqbSessionContextHolder.releaseSession();
                }
            }
        }
        if (exist) {
            return JsonResult.buildSuccessResult("token valid", token);
        } else {
            return JsonResult.buildErrorStateResult("token invalid", token);
        }
    }

    /**
     * 校验短信验证码
     *
     * @param phoneNo
     * @param verificationCode
     */
    @IpValidator
    @RequestMapping(value = "/verifyPhoneAndCode", method = RequestMethod.POST)
    public JsonResult verifyPhoneAndCode(@RequestParam String phoneNo, @RequestParam String verificationCode) {
        if (!smsService.verifyPhoneAndCode(phoneNo, verificationCode)) {
            // 是否需要重新发送短信验证码
            if (smsService.needResendCode(phoneNo)) {
                throw new VerificationCodeErrorException("验证码失效，请重新获取");
            }
            log.info("验证码校验失败,phoneNo:{} , verificationCode:{}", phoneNo, verificationCode);
            throw new VerificationCodeErrorException("短信验证码错误");
        }
        return JsonResult.buildSuccessResult(null);
    }

}
